Explorar el Código

feat: Add swagger support

chris hace 1 año
padre
commit
aa00079f15
Se han modificado 14 ficheros con 852 adiciones y 1003 borrados
  1. 6 1
      Makefile
  2. 99 80
      README.md
  3. 101 53
      README_zh.md
  4. 19 1
      cmd/server/main.go
  5. 200 0
      docs/docs.go
  6. 176 0
      docs/swagger.json
  7. 117 0
      docs/swagger.yaml
  8. 59 3
      go.mod
  9. 26 843
      go.sum
  10. 26 5
      internal/handler/user.go
  11. 8 13
      internal/pkg/request/user.go
  12. 3 3
      internal/pkg/response/response.go
  13. 11 0
      internal/server/http.go
  14. 1 1
      internal/service/user.go

+ 6 - 1
Makefile

@@ -2,6 +2,7 @@
 init:
 	go install github.com/google/wire/cmd/wire@latest
 	go install github.com/golang/mock/mockgen@latest
+	go install github.com/swaggo/swag/cmd/swag@latest
 
 .PHONY: bootstrap
 bootstrap:
@@ -26,4 +27,8 @@ build:
 .PHONY: docker
 docker:
 	docker build -f deploy/build/Dockerfile --build-arg APP_RELATIVE_PATH=./cmd/job -t 1.1.1.1:5000/demo-job:v1 .
-	docker run --rm -i 1.1.1.1:5000/demo-job:v1
+	docker run --rm -i 1.1.1.1:5000/demo-job:v1
+
+.PHONY: swag
+swag:
+	swag init  -g cmd/server/main.go -o ./docs --parseDependency

+ 99 - 80
README.md

@@ -1,8 +1,8 @@
-# nunu-layout-advanced - Advanced Layout
+# Nunu — A CLI tool for building Go applications.
 
-Nunu is an application scaffold based on Golang. Its name comes from a game character in League of Legends, a little boy riding on the shoulder of a yeti. Like Nunu, this project also stands on the shoulders of giants. It is a composition of various popular libraries from the Golang ecosystem, which can help you quickly build efficient and reliable applications.
+Nunu is a scaffolding tool for building Go applications. Its name comes from a game character in League of Legends, a little boy riding on the shoulders of a Yeti. Just like Nunu, this project stands on the shoulders of giants, as it is built upon a combination of popular libraries from the Go ecosystem. This combination allows you to quickly build efficient and reliable applications.
 
-[简体中文介绍](https://github.com/go-nunu/nunu-layout-advanced/blob/main/README_zh.md)
+[简体中文介绍](https://github.com/go-nunu/nunu/blob/main/README_zh.md)
 
 ![Nunu](https://github.com/go-nunu/nunu/blob/main/.github/assets/banner.png)
 
@@ -10,6 +10,8 @@ Nunu is an application scaffold based on Golang. Its name comes from a game char
 * [User Guide](https://github.com/go-nunu/nunu/blob/main/docs/en/guide.md)
 * [Architecture](https://github.com/go-nunu/nunu/blob/main/docs/en/architecture.md)
 * [Getting Started Tutorial](https://github.com/go-nunu/nunu/blob/main/docs/en/tutorial.md)
+* [Unit Testing](https://github.com/go-nunu/nunu/blob/main/docs/en/unit_testing.md)
+
 
 ## Features
 - **Gin**: https://github.com/gin-gonic/gin
@@ -21,113 +23,130 @@ Nunu is an application scaffold based on Golang. Its name comes from a game char
 - **Go-redis**: https://github.com/go-redis/redis
 - **Testify**: https://github.com/stretchr/testify
 - **Sonyflake**: https://github.com/sony/sonyflake
-- **gocron**:  https://github.com/go-co-op/gocron
+- **Gocron**:  https://github.com/go-co-op/gocron
+- **Go-sqlmock**:  https://github.com/DATA-DOG/go-sqlmock
+- **Gomock**:  https://github.com/golang/mock
+- **Swaggo**:  https://github.com/swaggo/swag
 - More...
 
-## Highlights
-* **Low Learning Curve and Customization**: Nunu encapsulates popular libraries that Gophers are familiar with. You can easily customize the application to meet specific requirements.
-* **High Performance and Scalability**: Nunu aims to be high-performance and scalable. It utilizes the latest technologies and best practices to ensure your application can handle high traffic and large data volumes.
+## Key Features
+* **Low Learning Curve and Customization**: Nunu encapsulates popular libraries that Gophers are familiar with, allowing you to easily customize the application to meet specific requirements.
+* **High Performance and Scalability**: Nunu aims to be high-performance and scalable. It uses the latest technologies and best practices to ensure that your application can handle high traffic and large amounts of data.
 * **Security and Reliability**: Nunu uses stable and reliable third-party libraries to ensure the security and reliability of your application.
-* **Modularity and Extensibility**: Nunu is designed to be modular and extensible. You can easily add new features and functionalities by using third-party libraries or writing your own modules.
-* **Comprehensive Documentation and Test Coverage**: Nunu has comprehensive documentation and test coverage. It provides detailed documentation and examples to help you get started quickly. It also includes a test suite to ensure your application works as expected.
+* **Modular and Extensible**: Nunu is designed to be modular and extensible. You can easily add new features and functionality by using third-party libraries or writing your own modules.
+* **Complete Documentation and Testing**: Nunu has comprehensive documentation and testing. It provides extensive documentation and examples to help you get started quickly. It also includes a test suite to ensure that your application works as expected.
+
+## Concise Layered Architecture
+Nunu adopts a classic layered architecture. In order to achieve modularity and decoupling, it uses the dependency injection framework `Wire`.
+
+![Nunu Layout](https://github.com/go-nunu/nunu/blob/main/.github/assets/layout.png)
 
 ## Nunu CLI
 
 ![Nunu](https://github.com/go-nunu/nunu/blob/main/.github/assets/screenshot.jpg)
 
+
 ## Directory Structure
 ```
 .
 ├── cmd
-│   └── server
-│       ├── main.go
-│       ├── wire.go
-│       └── wire_gen.go
+│   └── server
+│       ├── wire
+│       │   ├── wire.go
+│       │   └── wire_gen.go
+│       └── main.go
 ├── config
-│   ├── local.yml
-│   └── prod.yml
+│   ├── local.yml
+│   └── prod.yml
+├── deploy
 ├── internal
-│   ├── handler
-│   │   ├── handler.go
-│   │   └── user.go
-│   ├── middleware
-│   │   └── cors.go
-│   ├── model
-│   │   └── user.go
-│   ├── repository
-│   │   ├── repository.go
-│   │   └── user.go
-│   ├── server
-│   │   └── http.go
-│   └── service
-│       ├── service.go
-│       └── user.go
+│   ├── handler
+│   │   ├── handler.go
+│   │   └── user.go
+│   ├── job
+│   │   └── job.go
+│   ├── model
+│   │   └── user.go
+│   ├── pkg
+│   ├── repository
+│   │   ├── repository.go
+│   │   └── user.go
+│   ├── server
+│   │   ├── http.go
+│   │   └── server.go
+│   └── service
+│       ├── service.go
+│       └── user.go
 ├── pkg
-├── LICENSE
-├── README.md
-├── README_zh.md
+├── scripts
+├── storage
+├── test
+├── web
+├── Makefile
 ├── go.mod
 └── go.sum
 
 ```
 
-This is a classic directory structure for a Golang project, which includes the following directories:
-
-- cmd: Contains the entry points of the application, including the main function and dependency injection code.
-  - server: The main entry point of the application, including the main function and dependency injection code.
-    - main.go: The main function used to start the application.
-    - wire.go: The dependency injection code generated using Wire.
-    - wire_gen.go: The dependency injection code generated using Wire.
-
-- config: Contains the configuration files of the application.
-  - local.yml: The configuration file for the local environment.
-  - prod.yml: The configuration file for the production environment.
-
-- internal: Contains the internal code of the application.
-  - handler: Contains the handlers for handling HTTP requests.
-    - handler.go: The common handler for handling HTTP requests.
-    - user.go: The handler for handling user-related HTTP requests.
-  - middleware: Contains the middleware code.
-    - cors.go: The CORS (Cross-Origin Resource Sharing) middleware.
-  - model: Contains the data model code.
-    - user.go: The user data model.
-  - repository: Contains the data access code.
-    - repository.go: The common interface for data access.
-    - user.go: The implementation of the user data access interface.
-  - server: Contains the server code.
-    - http.go: The implementation of the HTTP server.
-  - service: Contains the business logic code.
-    - service.go: The common interface for business logic.
-    - user.go: The implementation of the user business logic.
-
-- pkg: Contains the public packages of the application.
-- storage: Contains the storage files of the application.
-- go.mod: The Go module file.
-- go.sum: The dependency versions file for the Go module.
+The project architecture follows a typical layered structure, consisting of the following modules:
+
+* `cmd`: This module contains the entry points of the application, which perform different operations based on different commands, such as starting the server or executing database migrations. Each sub-module has a `main.go` file as the entry file, as well as `wire.go` and `wire_gen.go` files for dependency injection.
+* `config`: This module contains the configuration files for the application, providing different configurations for different environments, such as development and production.
+* `deploy`: This module is used for deploying the application and includes deployment scripts and configuration files.
+* `internal`: This module is the core module of the application and contains the implementation of various business logic.
+
+  - `handler`: This sub-module contains the handlers for handling HTTP requests, responsible for receiving requests and invoking the corresponding services for processing.
+
+  - `job`: This sub-module contains the logic for background tasks.
+
+  - `model`: This sub-module contains the definition of data models.
+
+  - `repository`: This sub-module contains the implementation of the data access layer, responsible for interacting with the database.
+
+  - `server`: This sub-module contains the implementation of the HTTP server.
+
+  - `service`: This sub-module contains the implementation of the business logic, responsible for handling specific business operations.
+
+* `pkg`: This module contains some common utilities and functions.
+
+* `scripts`: This module contains some script files used for project build, test, and deployment operations.
+
+* `storage`: This module is used for storing files or other static resources.
+
+* `test`: This module contains the unit tests for various modules, organized into sub-directories based on modules.
+
+* `web`: This module contains the frontend-related files, such as HTML, CSS, and JavaScript.
+
+In addition, there are some other files and directories, such as license files, build files, and README. Overall, the project architecture is clear, with clear responsibilities for each module, making it easy to understand and maintain.
 
 ## Requirements
 To use Nunu, you need to have the following software installed on your system:
 
-* Golang 1.16 or higher
+* Go 1.19 or higher
 * Git
+* Docker (optional)
+* MySQL 5.7 or higher (optional)
+* Redis (optional)
 
 ### Installation
 
-You can install Nunu using the following command:
+You can install Nunu with the following command:
 
 ```bash
 go install github.com/go-nunu/nunu@latest
 ```
 
-### Creating a New Project
+> Tips: If `go install` succeeds but the `nunu` command is not recognized, it is because the environment variable is not configured. You can add the GOBIN directory to the environment variable.
+
+### Create a New Project
 
-You can create a new Golang project using the following command:
+You can create a new Go project with the following command:
 
 ```bash
 nunu new projectName
 ```
 
-By default, it will pull from the GitHub repository, but you can also use a mirror repository for faster access:
+By default, it pulls from the GitHub source, but you can also use an accelerated repository in China:
 
 ```
 // Use the basic template
@@ -136,9 +155,9 @@ nunu new projectName -r https://gitee.com/go-nunu/nunu-layout-basic.git
 nunu new projectName -r https://gitee.com/go-nunu/nunu-layout-advanced.git
 ```
 
-This command will create a directory named `projectName` and generate an elegant Golang project structure within it.
+This command will create a directory named `projectName` and generate an elegant Go project structure within it.
 
-### Creating Components
+### Create Components
 
 You can create handlers, services, repositories, and models for your project using the following commands:
 
@@ -153,21 +172,21 @@ or
 nunu create all user
 ```
 
-These commands will create components named `UserHandler`, `UserService`, `UserDao`, and `UserModel` respectively and place them in the correct directories.
+These commands will create components named `UserHandler`, `UserService`, `UserRepository`, and `UserModel`, respectively, and place them in the correct directories.
 
-### Starting the Project
+### Run the Project
 
-You can quickly start your project using the following command:
+You can quickly run the project with the following command:
 
 ```bash
 nunu run
 ```
 
-This command will start your Golang project and support hot-reloading of files.
+This command will start your Go project and support hot-reloading when files are updated.
 
-### Compiling wire.go
+### Compile wire.go
 
-You can quickly compile `wire.go` using the following command:
+You can quickly compile `wire.go` with the following command:
 
 ```bash
 nunu wire
@@ -181,4 +200,4 @@ If you find any issues or have any improvement suggestions, please feel free to
 
 ## License
 
-Nunu is released under the MIT License. See the [LICENSE](LICENSE) file for more information.
+Nunu is released under the MIT License. For more information, see the [LICENSE](LICENSE) file.

+ 101 - 53
README_zh.md

@@ -1,17 +1,17 @@
-# nunu-layout-advanced — 高级布局
+# Nunu — A CLI tool for building go aplication.
 
 
 Nunu是一个基于Golang的应用脚手架,它的名字来自于英雄联盟中的游戏角色,一个骑在雪怪肩膀上的小男孩。和努努一样,该项目也是站在巨人的肩膀上,它是由Golang生态中各种非常流行的库整合而成的,它们的组合可以帮助你快速构建一个高效、可靠的应用程序。
 
-[英文介绍](https://github.com/go-nunu/nunu-layout-advanced/blob/main/README.md
+[英文介绍](https://github.com/go-nunu/nunu/blob/main/README.md)
 
 ![Nunu](https://github.com/go-nunu/nunu/blob/main/.github/assets/banner.png)
 
-
 ## 文档
 * [使用指南](https://github.com/go-nunu/nunu/blob/main/docs/zh/guide.md)
 * [分层架构](https://github.com/go-nunu/nunu/blob/main/docs/zh/architecture.md)
 * [上手教程](https://github.com/go-nunu/nunu/blob/main/docs/zh/tutorial.md)
+* [高效编写单元测试](https://github.com/go-nunu/nunu/blob/main/docs/zh/unit_testing.md)
 
 ## 功能
 - **Gin**: https://github.com/gin-gonic/gin
@@ -23,7 +23,10 @@ Nunu是一个基于Golang的应用脚手架,它的名字来自于英雄联盟
 - **Go-redis**: https://github.com/go-redis/redis
 - **Testify**: https://github.com/stretchr/testify
 - **Sonyflake**: https://github.com/sony/sonyflake
-- **gocron**:  https://github.com/go-co-op/gocron
+- **Gocron**:  https://github.com/go-co-op/gocron
+- **Go-sqlmock**:  https://github.com/DATA-DOG/go-sqlmock
+- **Gomock**:  https://github.com/golang/mock
+- **Swaggo**:  https://github.com/swaggo/swag
 - More...
 ## 特性
 * **超低学习成本和定制**:Nunu封装了Gopher最熟悉的一些流行库。您可以轻松定制应用程序以满足特定需求。
@@ -32,86 +35,104 @@ Nunu是一个基于Golang的应用脚手架,它的名字来自于英雄联盟
 * **模块化和可扩展**:Nunu旨在具有模块化和可扩展性。您可以通过使用第三方库或编写自己的模块轻松添加新功能和功能。
 * **文档完善和测试完备**:Nunu文档完善,测试完备。它提供了全面的文档和示例,帮助您快速入门。它还包括一套测试套件,确保您的应用程序按预期工作。
 
+## 交流群组
+
+微信入群,请备注Nunu
+
+<p align="left"><img src="https://github.com/go-nunu/nunu/blob/main/.github/assets/qrcode.jpg" width="200"></p>
+
+## 简洁分层架构
+Nunu采用了经典的分层架构。同时,为了更好地实现模块化和解耦,采用了依赖注入框架`Wire`。
+
+![Nunu Layout](https://github.com/go-nunu/nunu/blob/main/.github/assets/layout.png)
+
 ## Nunu CLI
 
 ![Nunu](https://github.com/go-nunu/nunu/blob/main/.github/assets/screenshot.jpg)
 
 
+
 ## 目录结构
 ```
 .
 ├── cmd
 │   └── server
-│       ├── main.go
-│       ├── wire.go
-│       └── wire_gen.go
+│       ├── wire
+│       │   ├── wire.go
+│       │   └── wire_gen.go
+│       └── main.go
 ├── config
 │   ├── local.yml
 │   └── prod.yml
+├── deploy
 ├── internal
 │   ├── handler
 │   │   ├── handler.go
 │   │   └── user.go
-│   ├── middleware
-│   │   └── cors.go
+│   ├── job
+│   │   └── job.go
 │   ├── model
 │   │   └── user.go
+│   ├── pkg
 │   ├── repository
 │   │   ├── repository.go
 │   │   └── user.go
 │   ├── server
-│   │   └── http.go
+│   │   ├── http.go
+│   │   └── server.go
 │   └── service
 │       ├── service.go
 │       └── user.go
 ├── pkg
-├── LICENSE
-├── README.md
-├── README_zh.md
+├── scripts
+├── storage
+├── test
+├── web
+├── Makefile
 ├── go.mod
 └── go.sum
 
 ```
 
-这是一个经典的Golang 项目的目录结构,包含以下目录:
-
-- cmd: 存放应用程序的入口点,包括主函数和依赖注入的代码。
-  - server: 应用程序的主要入口点,包含主函数和依赖注入的代码。
-    - main.go: 主函数,用于启动应用程序。
-    - wire.go: 使用Wire库生成的依赖注入代码。
-    - wire_gen.go: 使用Wire库生成的依赖注入代码。
-
-- config: 存放应用程序的配置文件。
-  - local.yml: 本地环境的配置文件。
-  - prod.yml: 生产环境的配置文件。
-
-- internal: 存放应用程序的内部代码。
-  - handler: 处理HTTP请求的处理程序。
-    - handler.go: 处理HTTP请求的通用处理程序。
-    - user.go: 处理用户相关的HTTP请求的处理程序。
-  - middleware: 存放中间件代码。
-    - cors.go: 跨域资源共享中间件。
-  - model: 存放数据模型代码。
-    - user.go: 用户数据模型。
-  - repository: 存放数据访问代码。
-    - repository.go: 数据访问的通用接口。
-    - user.go: 用户数据访问接口的实现。
-  - server: 存放服务器代码。
-    - http.go: HTTP服务器的实现。
-  - service: 存放业务逻辑代码。
-    - service.go: 业务逻辑的通用接口。
-    - user.go: 用户业务逻辑的实现。
-
-- pkg: 存放应用程序的公共包。
-- storage: 存放应用程序的存储文件。
-- go.mod: Go模块文件。
-- go.sum: Go模块的依赖版本文件。
+该项目的架构采用了典型的分层架构,主要包括以下几个模块:
+
+* `cmd`:该模块包含了应用的入口点,根据不同的命令进行不同的操作,例如启动服务器、执行数据库迁移等。每个子模块都有一个`main.go`文件作为入口文件,以及`wire.go`和`wire_gen.go`文件用于依赖注入。
+* `config`:该模块包含了应用的配置文件,根据不同的环境(如开发环境和生产环境)提供不同的配置。
+* `deploy`:该模块用于部署应用,包含了一些部署脚本和配置文件。
+* `internal`:该模块是应用的核心模块,包含了各种业务逻辑的实现。
+
+  - `handler`:该子模块包含了处理HTTP请求的处理器,负责接收请求并调用相应的服务进行处理。
+
+  - `job`:该子模块包含了后台任务的逻辑实现。
+
+  - `model`:该子模块包含了数据模型的定义。
+
+  - `repository`:该子模块包含了数据访问层的实现,负责与数据库进行交互。
+
+  - `server`:该子模块包含了HTTP服务器的实现。
+
+  - `service`:该子模块包含了业务逻辑的实现,负责处理具体的业务操作。
+
+* `pkg`:该模块包含了一些通用的功能和工具。
+
+* `scripts`:该模块包含了一些脚本文件,用于项目的构建、测试和部署等操作。
+
+* `storage`:该模块用于存储文件或其他静态资源。
+
+* `test`:该模块包含了各个模块的单元测试,按照模块划分子目录。
+
+* `web`:该模块包含了前端相关的文件,如HTML、CSS和JavaScript等。
+
+此外,还包含了一些其他的文件和目录,如授权文件、构建文件、README等。整体上,该项目的架构清晰,各个模块之间的职责明确,便于理解和维护。
 
 ## 要求
 要使用Nunu,您需要在系统上安装以下软件:
 
-* Golang 1.16或更高版本
+* Golang 1.19或更高版本
 * Git
+* Docker (可选)
+* MySQL5.7或更高版本(可选)
+* Redis(可选)
 
 
 
@@ -123,27 +144,54 @@ Nunu是一个基于Golang的应用脚手架,它的名字来自于英雄联盟
 go install github.com/go-nunu/nunu@latest
 ```
 
+国内用户可以使用`GOPROXY`加速`go install`
+
+```
+$ go env -w GO111MODULE=on
+$ go env -w GOPROXY=https://goproxy.cn,direct
+```
+
+> tips: 如果`go install`成功,却提示找不到nunu命令,这是因为环境变量没有配置,可以把 GOBIN 目录配置到环境变量中即可
+
 
 ### 创建新项目
 
 您可以使用以下命令创建一个新的Golang项目:
 
 ```bash
+// 推荐新用户选择Advanced Layout
 nunu new projectName
 ```
-默认拉取github源,你也可以使用国内加速仓库
+
+`nunu new`默认拉取github源,你也可以使用国内加速仓库
 ```
+// 使用高级模板(推荐)
+nunu new projectName -r https://gitee.com/go-nunu/nunu-layout-advanced.git
+
 // 使用基础模板
 nunu new projectName -r https://gitee.com/go-nunu/nunu-layout-basic.git
-// 使用高级模板
-nunu new projectName -r https://gitee.com/go-nunu/nunu-layout-advanced.git
+
 ```
 
+
+> Nunu内置了两种类型的Layout:
+
+* **基础模板(Basic Layout)**
+
+Basic Layout 包含一个非常精简的架构目录结构,适合非常熟悉Nunu项目的开发者使用。
+
+* **高级模板(Advanced Layout)**
+
+**建议:我们推荐新手优先选择使用Advanced Layout。**
+
+
+Advanced Layout 包含了很多Nunu的用法示例( db、redis、 jwt、 cron、 migration等),适合开发者快速学习了解Nunu的架构思想。
+
 此命令将创建一个名为`projectName`的目录,并在其中生成一个优雅的Golang项目结构。
 
 ### 创建组件
 
-您可以使用以下命令为项目创建handler、service和dao等组件:
+您可以使用以下命令为项目创建handler、service、repository和model等组件:
 
 ```bash
 nunu create handler user
@@ -155,7 +203,7 @@ nunu create model user
 ```
 nunu create all user
 ```
-这些命令将分别创建一个名为`UserHandler`、`UserService`、`UserDao`和`UserModel`的组件,并将它们放置在正确的目录中。
+这些命令将分别创建一个名为`UserHandler`、`UserService`、`UserRepository`和`UserModel`的组件,并将它们放置在正确的目录中。
 
 ### 启动项目
 
@@ -183,4 +231,4 @@ nunu wire
 
 ## 许可证
 
-Nunu是根据MIT许可证发布的。有关更多信息,请参见[LICENSE](LICENSE)文件。
+Nunu是根据MIT许可证发布的。有关更多信息,请参见[LICENSE](LICENSE)文件。

+ 19 - 1
cmd/server/main.go

@@ -9,6 +9,22 @@ import (
 	"go.uber.org/zap"
 )
 
+// @title           Nunu Example API
+// @version         1.0.0
+// @description     This is a sample server celler server.
+// @termsOfService  http://swagger.io/terms/
+// @contact.name   API Support
+// @contact.url    http://www.swagger.io/support
+// @contact.email  support@swagger.io
+// @license.name  Apache 2.0
+// @license.url   http://www.apache.org/licenses/LICENSE-2.0.html
+// @host      localhost:8000
+// @BasePath  /
+// @securityDefinitions.apiKey Bearer
+// @in header
+// @name Authorization
+// @externalDocs.description  OpenAPI
+// @externalDocs.url          https://swagger.io/resources/open-api/
 func main() {
 	conf := config.NewConfig()
 	logger := log.NewLog(conf)
@@ -17,9 +33,11 @@ func main() {
 	if err != nil {
 		panic(err)
 	}
+
 	logger.Info("server start", zap.String("host", "http://localhost:"+conf.GetString("http.port")))
+	logger.Info("docs addr", zap.String("addr", fmt.Sprintf("http://127.0.0.1:%d/swagger/index.html", conf.GetInt("http.port"))))
 
-	//servers.
+	//go grpc.Run(servers.ServerGRPC, conf)
 	http.Run(servers.ServerHTTP, fmt.Sprintf(":%d", conf.GetInt("http.port")))
 	defer cleanup()
 

+ 200 - 0
docs/docs.go

@@ -0,0 +1,200 @@
+// Package docs Code generated by swaggo/swag. DO NOT EDIT
+package docs
+
+import "github.com/swaggo/swag"
+
+const docTemplate = `{
+    "schemes": {{ marshal .Schemes }},
+    "swagger": "2.0",
+    "info": {
+        "description": "{{escape .Description}}",
+        "title": "{{.Title}}",
+        "termsOfService": "http://swagger.io/terms/",
+        "contact": {
+            "name": "API Support",
+            "url": "http://www.swagger.io/support",
+            "email": "support@swagger.io"
+        },
+        "license": {
+            "name": "Apache 2.0",
+            "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
+        },
+        "version": "{{.Version}}"
+    },
+    "host": "{{.Host}}",
+    "basePath": "{{.BasePath}}",
+    "paths": {
+        "/login": {
+            "post": {
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "用户模块"
+                ],
+                "summary": "账号登录",
+                "parameters": [
+                    {
+                        "description": "params",
+                        "name": "request",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/github_com_go-nunu_nunu-layout-advanced_internal_pkg_request.LoginRequest"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/github_com_go-nunu_nunu-layout-advanced_internal_pkg_response.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/register": {
+            "post": {
+                "description": "目前只支持邮箱登录",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "用户模块"
+                ],
+                "summary": "用户注册",
+                "parameters": [
+                    {
+                        "description": "params",
+                        "name": "request",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/github_com_go-nunu_nunu-layout-advanced_internal_pkg_request.RegisterRequest"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/github_com_go-nunu_nunu-layout-advanced_internal_pkg_response.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/user": {
+            "get": {
+                "security": [
+                    {
+                        "Bearer": []
+                    }
+                ],
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "用户模块"
+                ],
+                "summary": "获取用户信息",
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/github_com_go-nunu_nunu-layout-advanced_internal_pkg_response.Response"
+                        }
+                    }
+                }
+            }
+        }
+    },
+    "definitions": {
+        "github_com_go-nunu_nunu-layout-advanced_internal_pkg_request.LoginRequest": {
+            "type": "object",
+            "required": [
+                "password",
+                "username"
+            ],
+            "properties": {
+                "password": {
+                    "type": "string",
+                    "example": "123456"
+                },
+                "username": {
+                    "type": "string",
+                    "example": "alan"
+                }
+            }
+        },
+        "github_com_go-nunu_nunu-layout-advanced_internal_pkg_request.RegisterRequest": {
+            "type": "object",
+            "required": [
+                "email",
+                "password",
+                "username"
+            ],
+            "properties": {
+                "email": {
+                    "type": "string",
+                    "example": "1234@gmail.com"
+                },
+                "password": {
+                    "type": "string",
+                    "example": "123456"
+                },
+                "username": {
+                    "type": "string",
+                    "example": "alan"
+                }
+            }
+        },
+        "github_com_go-nunu_nunu-layout-advanced_internal_pkg_response.Response": {
+            "type": "object",
+            "properties": {
+                "code": {
+                    "type": "integer"
+                },
+                "data": {},
+                "message": {
+                    "type": "string"
+                }
+            }
+        }
+    },
+    "securityDefinitions": {
+        "Bearer": {
+            "type": "apiKey",
+            "name": "Authorization",
+            "in": "header"
+        }
+    }
+}`
+
+// SwaggerInfo holds exported Swagger Info so clients can modify it
+var SwaggerInfo = &swag.Spec{
+	Version:          "1.0.0",
+	Host:             "localhost:8000",
+	BasePath:         "/",
+	Schemes:          []string{},
+	Title:            "Nunu Example API",
+	Description:      "This is a sample server celler server.",
+	InfoInstanceName: "swagger",
+	SwaggerTemplate:  docTemplate,
+	LeftDelim:        "{{",
+	RightDelim:       "}}",
+}
+
+func init() {
+	swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
+}

+ 176 - 0
docs/swagger.json

@@ -0,0 +1,176 @@
+{
+    "swagger": "2.0",
+    "info": {
+        "description": "This is a sample server celler server.",
+        "title": "Nunu Example API",
+        "termsOfService": "http://swagger.io/terms/",
+        "contact": {
+            "name": "API Support",
+            "url": "http://www.swagger.io/support",
+            "email": "support@swagger.io"
+        },
+        "license": {
+            "name": "Apache 2.0",
+            "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
+        },
+        "version": "1.0.0"
+    },
+    "host": "localhost:8000",
+    "basePath": "/",
+    "paths": {
+        "/login": {
+            "post": {
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "用户模块"
+                ],
+                "summary": "账号登录",
+                "parameters": [
+                    {
+                        "description": "params",
+                        "name": "request",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/github_com_go-nunu_nunu-layout-advanced_internal_pkg_request.LoginRequest"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/github_com_go-nunu_nunu-layout-advanced_internal_pkg_response.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/register": {
+            "post": {
+                "description": "目前只支持邮箱登录",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "用户模块"
+                ],
+                "summary": "用户注册",
+                "parameters": [
+                    {
+                        "description": "params",
+                        "name": "request",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/github_com_go-nunu_nunu-layout-advanced_internal_pkg_request.RegisterRequest"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/github_com_go-nunu_nunu-layout-advanced_internal_pkg_response.Response"
+                        }
+                    }
+                }
+            }
+        },
+        "/user": {
+            "get": {
+                "security": [
+                    {
+                        "Bearer": []
+                    }
+                ],
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "用户模块"
+                ],
+                "summary": "获取用户信息",
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/github_com_go-nunu_nunu-layout-advanced_internal_pkg_response.Response"
+                        }
+                    }
+                }
+            }
+        }
+    },
+    "definitions": {
+        "github_com_go-nunu_nunu-layout-advanced_internal_pkg_request.LoginRequest": {
+            "type": "object",
+            "required": [
+                "password",
+                "username"
+            ],
+            "properties": {
+                "password": {
+                    "type": "string",
+                    "example": "123456"
+                },
+                "username": {
+                    "type": "string",
+                    "example": "alan"
+                }
+            }
+        },
+        "github_com_go-nunu_nunu-layout-advanced_internal_pkg_request.RegisterRequest": {
+            "type": "object",
+            "required": [
+                "email",
+                "password",
+                "username"
+            ],
+            "properties": {
+                "email": {
+                    "type": "string",
+                    "example": "1234@gmail.com"
+                },
+                "password": {
+                    "type": "string",
+                    "example": "123456"
+                },
+                "username": {
+                    "type": "string",
+                    "example": "alan"
+                }
+            }
+        },
+        "github_com_go-nunu_nunu-layout-advanced_internal_pkg_response.Response": {
+            "type": "object",
+            "properties": {
+                "code": {
+                    "type": "integer"
+                },
+                "data": {},
+                "message": {
+                    "type": "string"
+                }
+            }
+        }
+    },
+    "securityDefinitions": {
+        "Bearer": {
+            "type": "apiKey",
+            "name": "Authorization",
+            "in": "header"
+        }
+    }
+}

+ 117 - 0
docs/swagger.yaml

@@ -0,0 +1,117 @@
+basePath: /
+definitions:
+  github_com_go-nunu_nunu-layout-advanced_internal_pkg_request.LoginRequest:
+    properties:
+      password:
+        example: "123456"
+        type: string
+      username:
+        example: alan
+        type: string
+    required:
+    - password
+    - username
+    type: object
+  github_com_go-nunu_nunu-layout-advanced_internal_pkg_request.RegisterRequest:
+    properties:
+      email:
+        example: 1234@gmail.com
+        type: string
+      password:
+        example: "123456"
+        type: string
+      username:
+        example: alan
+        type: string
+    required:
+    - email
+    - password
+    - username
+    type: object
+  github_com_go-nunu_nunu-layout-advanced_internal_pkg_response.Response:
+    properties:
+      code:
+        type: integer
+      data: {}
+      message:
+        type: string
+    type: object
+host: localhost:8000
+info:
+  contact:
+    email: support@swagger.io
+    name: API Support
+    url: http://www.swagger.io/support
+  description: This is a sample server celler server.
+  license:
+    name: Apache 2.0
+    url: http://www.apache.org/licenses/LICENSE-2.0.html
+  termsOfService: http://swagger.io/terms/
+  title: Nunu Example API
+  version: 1.0.0
+paths:
+  /login:
+    post:
+      consumes:
+      - application/json
+      parameters:
+      - description: params
+        in: body
+        name: request
+        required: true
+        schema:
+          $ref: '#/definitions/github_com_go-nunu_nunu-layout-advanced_internal_pkg_request.LoginRequest'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/github_com_go-nunu_nunu-layout-advanced_internal_pkg_response.Response'
+      summary: 账号登录
+      tags:
+      - 用户模块
+  /register:
+    post:
+      consumes:
+      - application/json
+      description: 目前只支持邮箱登录
+      parameters:
+      - description: params
+        in: body
+        name: request
+        required: true
+        schema:
+          $ref: '#/definitions/github_com_go-nunu_nunu-layout-advanced_internal_pkg_request.RegisterRequest'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/github_com_go-nunu_nunu-layout-advanced_internal_pkg_response.Response'
+      summary: 用户注册
+      tags:
+      - 用户模块
+  /user:
+    get:
+      consumes:
+      - application/json
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/github_com_go-nunu_nunu-layout-advanced_internal_pkg_response.Response'
+      security:
+      - Bearer: []
+      summary: 获取用户信息
+      tags:
+      - 用户模块
+securityDefinitions:
+  Bearer:
+    in: header
+    name: Authorization
+    type: apiKey
+swagger: "2.0"

+ 59 - 3
go.mod

@@ -1,6 +1,6 @@
 module github.com/go-nunu/nunu-layout-advanced
 
-go 1.16
+go 1.19
 
 require (
 	github.com/DATA-DOG/go-sqlmock v1.5.0
@@ -16,10 +16,66 @@ require (
 	github.com/sony/sonyflake v1.1.0
 	github.com/spf13/viper v1.16.0
 	github.com/stretchr/testify v1.8.4
-	go.uber.org/atomic v1.11.0 // indirect
+	github.com/swaggo/files v1.0.1
+	github.com/swaggo/gin-swagger v1.6.0
+	github.com/swaggo/swag v1.16.2
 	go.uber.org/zap v1.24.0
-	golang.org/x/crypto v0.9.0
+	golang.org/x/crypto v0.12.0
 	gopkg.in/natefinch/lumberjack.v2 v2.2.1
 	gorm.io/driver/mysql v1.5.1
 	gorm.io/gorm v1.25.1
 )
+
+require (
+	github.com/KyleBanks/depth v1.2.1 // indirect
+	github.com/bytedance/sonic v1.9.1 // indirect
+	github.com/cespare/xxhash/v2 v2.2.0 // indirect
+	github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
+	github.com/davecgh/go-spew v1.1.1 // indirect
+	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
+	github.com/fsnotify/fsnotify v1.6.0 // indirect
+	github.com/gabriel-vasile/mimetype v1.4.2 // indirect
+	github.com/gin-contrib/sse v0.1.0 // indirect
+	github.com/go-openapi/jsonpointer v0.20.0 // indirect
+	github.com/go-openapi/jsonreference v0.20.2 // indirect
+	github.com/go-openapi/spec v0.20.9 // indirect
+	github.com/go-openapi/swag v0.22.4 // indirect
+	github.com/go-playground/locales v0.14.1 // indirect
+	github.com/go-playground/universal-translator v0.18.1 // indirect
+	github.com/go-playground/validator/v10 v10.14.0 // indirect
+	github.com/go-sql-driver/mysql v1.7.0 // indirect
+	github.com/goccy/go-json v0.10.2 // indirect
+	github.com/hashicorp/hcl v1.0.0 // indirect
+	github.com/jinzhu/inflection v1.0.0 // indirect
+	github.com/jinzhu/now v1.1.5 // indirect
+	github.com/josharian/intern v1.0.0 // indirect
+	github.com/json-iterator/go v1.1.12 // indirect
+	github.com/klauspost/cpuid/v2 v2.2.4 // indirect
+	github.com/leodido/go-urn v1.2.4 // indirect
+	github.com/magiconair/properties v1.8.7 // indirect
+	github.com/mailru/easyjson v0.7.7 // indirect
+	github.com/mattn/go-isatty v0.0.19 // indirect
+	github.com/mitchellh/mapstructure v1.5.0 // indirect
+	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/pelletier/go-toml/v2 v2.0.8 // indirect
+	github.com/pmezard/go-difflib v1.0.0 // indirect
+	github.com/robfig/cron/v3 v3.0.1 // indirect
+	github.com/spf13/afero v1.9.5 // indirect
+	github.com/spf13/cast v1.5.1 // indirect
+	github.com/spf13/jwalterweatherman v1.1.0 // indirect
+	github.com/spf13/pflag v1.0.5 // indirect
+	github.com/subosito/gotenv v1.4.2 // indirect
+	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
+	github.com/ugorji/go/codec v1.2.11 // indirect
+	go.uber.org/atomic v1.11.0 // indirect
+	go.uber.org/multierr v1.8.0 // indirect
+	golang.org/x/arch v0.3.0 // indirect
+	golang.org/x/net v0.14.0 // indirect
+	golang.org/x/sys v0.12.0 // indirect
+	golang.org/x/text v0.13.0 // indirect
+	golang.org/x/tools v0.12.0 // indirect
+	google.golang.org/protobuf v1.30.0 // indirect
+	gopkg.in/ini.v1 v1.67.0 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+)

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 26 - 843
go.sum


+ 26 - 5
internal/handler/user.go

@@ -28,14 +28,15 @@ type userHandler struct {
 }
 
 // Register godoc
-// @Summary ping example
+// @Summary 用户注册
 // @Schemes
-// @Description do ping
-// @Tags example
+// @Description 目前只支持邮箱登录
+// @Tags 用户模块
 // @Accept json
 // @Produce json
-// @Success 200 {string} Helloworld
-// @Router /example/helloworld [get]
+// @Param request body request.RegisterRequest true "params"
+// @Success 200 {object} response.Response
+// @Router /register [post]
 func (h *userHandler) Register(ctx *gin.Context) {
 	req := new(request.RegisterRequest)
 	if err := ctx.ShouldBindJSON(req); err != nil {
@@ -51,6 +52,16 @@ func (h *userHandler) Register(ctx *gin.Context) {
 	response.HandleSuccess(ctx, nil)
 }
 
+// Login godoc
+// @Summary 账号登录
+// @Schemes
+// @Description
+// @Tags 用户模块
+// @Accept json
+// @Produce json
+// @Param request body request.LoginRequest true "params"
+// @Success 200 {object} response.Response
+// @Router /login [post]
 func (h *userHandler) Login(ctx *gin.Context) {
 	var req request.LoginRequest
 	if err := ctx.ShouldBindJSON(&req); err != nil {
@@ -69,6 +80,16 @@ func (h *userHandler) Login(ctx *gin.Context) {
 	})
 }
 
+// GetProfile godoc
+// @Summary 获取用户信息
+// @Schemes
+// @Description
+// @Tags 用户模块
+// @Accept json
+// @Produce json
+// @Security Bearer
+// @Success 200 {object} response.Response
+// @Router /user [get]
 func (h *userHandler) GetProfile(ctx *gin.Context) {
 	userId := GetUserIdFromCtx(ctx)
 	if userId == "" {

+ 8 - 13
internal/pkg/request/user.go

@@ -1,23 +1,18 @@
 package request
 
 type RegisterRequest struct {
-	Username string `json:"username" binding:"required"`
-	Password string `json:"password" binding:"required"`
-	Email    string `json:"email" binding:"required,email"`
+	Username string `json:"username" binding:"required" example:"alan"`
+	Password string `json:"password" binding:"required" example:"123456"`
+	Email    string `json:"email" binding:"required,email" example:"1234@gmail.com"`
 }
 
 type LoginRequest struct {
-	Username string `json:"username" binding:"required"`
-	Password string `json:"password" binding:"required"`
+	Username string `json:"username" binding:"required" example:"alan"`
+	Password string `json:"password" binding:"required" example:"123456"`
 }
 
 type UpdateProfileRequest struct {
-	Nickname string `json:"nickname"`
-	Email    string `json:"email" binding:"required,email"`
-	Avatar   string `json:"avatar"`
-}
-
-type ChangePasswordRequest struct {
-	OldPassword string `json:"oldPassword" binding:"required"`
-	NewPassword string `json:"newPassword" binding:"required"`
+	Nickname string `json:"nickname" example:"alan"`
+	Email    string `json:"email" binding:"required,email" example:"1234@gmail.com"`
+	Avatar   string `json:"avatar" example:"xxxx"`
 }

+ 3 - 3
internal/pkg/response/response.go

@@ -6,7 +6,7 @@ import (
 	"net/http"
 )
 
-type response struct {
+type Response struct {
 	Code    int         `json:"code"`
 	Message string      `json:"message"`
 	Data    interface{} `json:"data"`
@@ -16,7 +16,7 @@ func HandleSuccess(ctx *gin.Context, data interface{}) {
 	if data == nil {
 		data = map[string]string{}
 	}
-	resp := response{Code: errorCodeMap[ErrSuccess], Message: ErrSuccess.Error(), Data: data}
+	resp := Response{Code: errorCodeMap[ErrSuccess], Message: ErrSuccess.Error(), Data: data}
 	ctx.JSON(http.StatusOK, resp)
 }
 
@@ -24,7 +24,7 @@ func HandleError(ctx *gin.Context, httpCode int, err error, data interface{}) {
 	if data == nil {
 		data = map[string]string{}
 	}
-	resp := response{Code: errorCodeMap[err], Message: err.Error(), Data: data}
+	resp := Response{Code: errorCodeMap[err], Message: err.Error(), Data: data}
 	ctx.JSON(httpCode, resp)
 }
 

+ 11 - 0
internal/server/http.go

@@ -2,11 +2,14 @@ package server
 
 import (
 	"github.com/gin-gonic/gin"
+	"github.com/go-nunu/nunu-layout-advanced/docs"
 	"github.com/go-nunu/nunu-layout-advanced/internal/handler"
 	"github.com/go-nunu/nunu-layout-advanced/internal/pkg/middleware"
 	"github.com/go-nunu/nunu-layout-advanced/internal/pkg/response"
 	"github.com/go-nunu/nunu-layout-advanced/pkg/jwt"
 	"github.com/go-nunu/nunu-layout-advanced/pkg/log"
+	swaggerfiles "github.com/swaggo/files"
+	ginSwagger "github.com/swaggo/gin-swagger"
 )
 
 func NewServerHTTP(
@@ -17,6 +20,14 @@ func NewServerHTTP(
 	gin.SetMode(gin.ReleaseMode)
 	r := gin.Default()
 
+	// swagger doc
+	docs.SwaggerInfo.BasePath = "/"
+	r.GET("/swagger/*any", ginSwagger.WrapHandler(
+		swaggerfiles.Handler,
+		//ginSwagger.URL(fmt.Sprintf("http://localhost:%d/swagger/doc.json", conf.GetInt("app.http.port"))),
+		ginSwagger.DefaultModelsExpandDepth(-1),
+	))
+
 	r.Use(
 		middleware.CORSMiddleware(),
 		middleware.ResponseLogMiddleware(logger),

+ 1 - 1
internal/service/user.go

@@ -62,7 +62,7 @@ func (s *userService) Register(ctx context.Context, req *request.RegisterRequest
 func (s *userService) Login(ctx context.Context, req *request.LoginRequest) (string, error) {
 	user, err := s.userRepo.GetByUsername(ctx, req.Username)
 	if err != nil || user == nil {
-		return "", errors.Wrap(err, "failed to get user by username")
+		return "", response.ErrUnauthorized
 	}
 
 	err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password))

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio