Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update readme and add env copier #8

Merged
merged 1 commit into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .extra/docs/goserve-banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .extra/docs/goserve-cover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
53 changes: 53 additions & 0 deletions .tools/copy/envs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package main

import (
"fmt"
"io"
"os"
)

func copyFile(src, dst string) error {
// Open the source file for reading
sourceFile, err := os.Open(src)
if err != nil {
return fmt.Errorf("could not open source file: %w", err)
}
defer sourceFile.Close()

// Create the destination file
destinationFile, err := os.Create(dst)
if err != nil {
return fmt.Errorf("could not create destination file: %w", err)
}
defer destinationFile.Close()

// Copy the contents of the source file to the destination file
_, err = io.Copy(destinationFile, sourceFile)
if err != nil {
return fmt.Errorf("could not copy file: %w", err)
}

// Ensure all data is flushed to the destination file
err = destinationFile.Sync()
if err != nil {
return fmt.Errorf("could not flush data to destination file: %w", err)
}

return nil
}

func main() {
err := copyFile(".env.example", ".env")
if err != nil {
fmt.Printf("Error copying file: %v\n", err)
return
}

err = copyFile(".test.env.example", ".test.env")
if err != nil {
fmt.Printf("Error copying file: %v\n", err)
return
}

fmt.Println("env files copied successfully!")
}
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ test:
cover:
go test -cover ./...

keygen:
setup:
go run .tools/rsa/keygen.go
go run .tools/copy/envs.go

# make apigen ARGS="sample"
apigen:
Expand Down
119 changes: 98 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,75 @@
# Go Backend Development - goserve
# goserve - Go Backend Architecture

## API Framework Design
[![Docker Compose CI](https://github.com/unusualcodeorg/goserve/actions/workflows/docker_compose.yml/badge.svg)](https://github.com/unusualcodeorg/goserve/actions/workflows/docker_compose.yml)

![Banner](.extra/docs/goserve-banner.png)

## Create A Blog Service

This project is a fully production-ready solution designed to implement best practices for building performant and secure backend REST API services. It provides a robust architectural framework to ensure consistency and maintain high code quality. The architecture emphasizes feature separation, facilitating easier unit and integration testing.

# Framework
- Go
- Gin
- jwt
- mongodriver
- go-redis
- Validator
- Viper
- Crypto

## Highlights
- API key support
- Token based Authentication
- Role based Authorization
- Unit Tests
- Integration Tests
- Modular codebase

# Architecture
The goal is to make each API independent from one another and only share services among them. This will make code reusable and reduce conflicts while working in a team.

The APIs will have separate directory based on the endpoint. Example `blog` and `blogs` will have seperate directory whereas `blog`, `blog/author`, and `blog/editor` will share common resources and will live inside same directory.

## Startup Flow
cmd/main → startup/server → module, mongo, redis, router → api/[feature]/middlewares → api/[feature]/controller -> api/[feature]/service, authentication, authorization → handlers → sender

## API Structure
```
Sample API
├── dto
│ └── create_sample.go
├── model
│ └── sample.go
├── controller.go
└── service.go
```

- Each feature API lives under `api` directory
- The request and response body is sent in the form of a DTO (Data Transfer Object) inside `dto` directory
- The database collection model lives inside `model` directory
- Controller is responsible for defining endpoints and corresponding handlers
- Service is the main logic component and handles data. Controller interact with a service to process a request. A service can also interact with other services.

# Project Directories
1. **api**: APIs code
2. **arch**: It provide framework and base implementation for creating the architecture
3. **cmd**: main function to start the program
4. **common**: code to be used in all the apis
5. **config**: load environment variables
6. **keys**: stores server pem files for token
7. **startup**: creates server and initializes database, redis, and router
8. **tests**: holds the integration tests
9. **utils**: contains utility functions

## Helper/Optional Directories
1. **.extra**: mongo script for initialization inside docker, other web assets and documents
2. **.github**: CI for tests
3. **.tools**: api code, RSA key generator, and .env copier
4. **.vscode**: editor config and debug launch settings


## API Design
![Request-Response-Design](.extra/docs/api-structure.png)

## API DOC
Expand All @@ -9,57 +78,65 @@
# Installation Instruction
vscode is the recommended editor - dark theme

### Get the repo
### 1. Get the repo

```bash
git clone https://github.com/unusualcodeorg/goserve.git
```

### Run Docker Compose
### 2. Generate RSA Keys
```
go run .tools/rsa/keygen.go
```

### 3. Create .env files
```
go run .tools/copy/envs.go
```

### 4. Run Docker Compose
- Install Docker and Docker Compose. [Find Instructions Here](https://docs.docker.com/install/).

```bash
docker-compose up --build
```
- You will be able to access the api from http://localhost:8080

### Run Tests
### 5. Run Tests
```bash
TODO
docker exec -t goserver go test -v ./...
```

If having any issue
- Make sure 8080 port is not occupied else change SERVER_PORT in **.env** file.
- Make sure 27017 port is not occupied else change DB_PORT in **.env** file.
- Make sure 6379 port is not occupied else change REDIS_PORT in **.env** file.

## Run on the local machine
Change the following hosts in the **.env**
- DB_HOST=localhost
- REDIS_HOST=localhost

Best way to run this project is to use the vscode `Run and Debug` button. Scripts are available for debugging and template generation on vscode.

# Run on the local machine
```bash
go mod tidy
```
or

```bash
make install
```
Keep the docker container for `mongo` and `redis` running and **stop** the `goserve` docker container

Change the following hosts in the **.env** and **.test.env**
- DB_HOST=localhost
- REDIS_HOST=localhost

### Running the app
Best way to run this project is to use the vscode `Run and Debug` button. Scripts are available for debugging and template generation on vscode.

### Optional - Running the app from terminal
```bash
go run cmd/main.go
```

or
# Template
New api creation can be done using command. `go run .tools/apigen.go [feature_name]`. This will create all the required skeleton files inside the directory api/[feature_name]

```bash
make run
go run .tools/apigen.go sample
```


## Find this project useful ? :heart:
* Support it by clicking the :star: button on the upper right of this page. :v:

Expand Down