Skip to content
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
15 changes: 11 additions & 4 deletions builder/hexagonal/hexagonal.go
Original file line number Diff line number Diff line change
Expand Up @@ -1765,10 +1765,17 @@ func (p *Project) GenerateMakefile() error {

// Readme
func (p *Project) GenerateReadmeFile() error {
data := map[string]string{
"ProjectName": p.based.Project.ProjectName,
"PackagePath": p.based.Project.PackagePath,
"AppName": p.based.Project.AppName,
data := map[string]any{
"ProjectName": p.based.Project.ProjectName,
"PackagePath": p.based.Project.PackagePath,
"AppName": p.based.Project.AppName,
"HasEndpoints": len(p.RoutesGroup) > 0,
"RouteGroups": p.RoutesGroup,
"Services": p.Service.Services,
"HasCache": p.cacheType != "",
"CacheType": p.cacheType,
"HasDatabase": p.dbType != "",
"DatabaseType": p.dbType,
}

raw, err := libos.ExecuteTemplate(p.ReadmeFile.template, data)
Expand Down
6 changes: 6 additions & 0 deletions examples/books-api/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ start: services init check-db run

# Target: Check if the database is up and running
check-db:
@echo "Checking if PostgreSQL is up..."
@until docker exec -it postgres_dev psql -U myapp -d myapp -c "\q" > /dev/null 2>&1; do \
echo "Waiting for PostgreSQL..."; \
sleep 2; \
done
@echo "PostgreSQL is up and ready."

# Declare these targets as phony (not associated with real files)
.PHONY: services init run build start check-db
155 changes: 76 additions & 79 deletions examples/books-api/README.md
Original file line number Diff line number Diff line change
@@ -1,93 +1,99 @@
# books-api

A brief description of the project, what it does, and its purpose.
API generated by [Rocket](https://github.com/muhfaris/rocket) from an OpenAPI 3.0 specification.

---

## Table of Contents

1. [Getting Started](#getting-started)
2. [Prerequisites](#prerequisites)
3. [Installation](#installation)
4. [Usage](#usage)
5. [Configuration](#configuration)
6. [Testing](#testing)
7. [Contributing](#contributing)
8. [License](#license)

---

## Getting Started

These instructions will help you get a copy of the project up and running on your local machine for development and testing purposes.

---

## Prerequisites

- Go (minimum version 1.22) installed on your system.
- [Optional] Docker for containerized deployment.

---

## Installation

### Clone the Repository
## Quick Start

```bash
git clone github.com/muhfaris/rocket/examples/books-api
cd repository
cd books-api
make start
```

### Initialize the Project
The server starts on `http://localhost:7000` (configurable in `config/config.yaml`).

Run the following command to prepare the project:
---

```bash
make init
```
## API Endpoints

This command will:

- Run `go mod tidy` to clean up dependencies.
- Run `go mod vendor` to vendor dependencies.
### bookGroup (prefix `/api/v1`)

### Quick Start
| Method | Path | Handler |
|--------|------|---------|
| `Get` | `/books/:bookId` | `GetBook` |
| `Get` | `/books` | `ListBooks` |
| `Post` | `/books` | `CreateBook` |
### borrowGroup (prefix `/api/v1`)

Run the following command to start the services, gomod application and run the application:
| Method | Path | Handler |
|--------|------|---------|
| `Post` | `/books/:bookId/borrow` | `BorrowBook` |
| `Patch` | `/books/:bookId/return` | `ReturnBook` |
### routeGroup (prefix `/`)

| Method | Path | Handler |
|--------|------|---------|
| `Get` | `/health` | `HealthCheck` |

```bash
make start
```
---

## Usage
## Architecture

### Running the Application
This project follows **hexagonal architecture** (ports & adapters):

```bash
go run main.go rest
```
HTTP Request
┌─ INBOUND ADAPTER ────────────────────────┐
│ Router → Handler → Presenter │ auto-generated
│ (internal/adapter/inbound/rest/) │
└──────────────────┬───────────────────────┘
│ calls interface
┌─ CORE ───────────────────────────────────┐
│ Service Interface (port) │ contract
│ Service Impl (domain) ← YOUR CODE│ business logic
│ Repository Interface (port) │ contract
└──────────────────┬───────────────────────┘
│ implements
┌─ OUTBOUND ADAPTER ───────────────────────┐
│ DB Adapter → PostgreSQL / MySQL /… │ auto-generated
│ Cache Adapter → Redis / in-memory │
└──────────────────────────────────────────┘
```

or
### Key directories

```bash
make run
```
| Directory | Purpose |
|-----------|---------|
| `internal/adapter/inbound/rest/router/v1/handler/` | HTTP handlers — parse requests, call services (auto-generated) |
| `internal/adapter/inbound/rest/router/v1/presenter/` | Map domain models → API responses (TODO stubs — update these) |
| `internal/core/port/inbound/service/` | Service interfaces |
| `internal/core/service/` | **Business logic goes here** — each method is a stub returning an error |
| `internal/core/domain/` | Domain models |
| `internal/core/port/outbound/` | Repository interfaces |
| `internal/adapter/outbound/` | Database/cache implementations
| `internal/adapter/outbound/datastore/postgresql/repository/` | Query implementations (TODO stubs)
| `internal/adapter/outbound/cache/redis/` | Cache adapter

### Build the Application
### Development workflow

```bash
make build
```
1. **Add business logic** → edit `internal/core/service/*.go`
2. **Add queries** → edit `internal/adapter/outbound/datastore/*/repository/*.go`
3. **Map responses** → edit `internal/adapter/inbound/rest/router/v1/presenter/*.go`
4. **Regenerate from spec** → run `rocket new` again (commit changes first — regeneration overwrites files)

---

## Configuration

Configuration is handled through `config/config.yaml`:
Edit `config/config.yaml`:

```env
```yaml
app:
name: books-api
port: 7000
Expand All @@ -113,28 +119,19 @@ app:

---

### Shortcuts Commands

The project comes with a set of shortcuts commands to make development easier:

- `make start` - Run the services, gomod application and run the application.
- `make services` - Start necessary services and remove old volume.
- `make run` - Run the application.
- `make build` - Build the application for deployment and store it in the `$(GOPATH)/bin` directory.
- `make init` - Run `go mod tidy` and `go mod vendor` commands.

## Contributing

Contributions are welcome! Please follow these steps:
## Makefile

1. Fork the repository.
2. Create a new branch (`git checkout -b feature-name`).
3. Commit your changes (`git commit -m 'Add new feature'`).
4. Push to the branch (`git push origin feature-name`).
5. Open a pull request.
| Command | Description |
|---------|-------------|
| `make start` | Start Docker services + run the application |
| `make services` | Start Docker services only (clean volumes) |
| `make run` | Run the application |
| `make build` | Build binary to `$(GOPATH)/bin` |
| `make init` | Run `go mod tidy` and `go mod vendor` |
| `make test` | Run tests |

---

## License
## Spec

This project is licensed under the [MIT License](LICENSE).
The OpenAPI spec used to generate this project is at `spec/openapi.yaml`. Edit it and regenerate to update the API.
35 changes: 33 additions & 2 deletions examples/books-api/cmd/bootstrap/app_repository.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,49 @@
package bootstrap

import (
"github.com/muhfaris/rocket/examples/books-api/config"
redisadapter "github.com/muhfaris/rocket/examples/books-api/internal/adapter/outbound/cache/redis"
psqladapter "github.com/muhfaris/rocket/examples/books-api/internal/adapter/outbound/datastore/psql"
pgsqlrepository "github.com/muhfaris/rocket/examples/books-api/internal/adapter/outbound/datastore/psql/repository"
portregistry "github.com/muhfaris/rocket/examples/books-api/internal/core/port/inbound/registry"
"github.com/muhfaris/rocket/examples/books-api/internal/core/port/outbound/repository"
)

func InitializeRepository() portregistry.Repository {
return &AppRepository{}
return &AppRepository{

cacheRepository: redisadapter.New(
redisadapter.RedisOptions{
Addr: config.App.Cache.Redis.Addr,
Username: config.App.Cache.Redis.Username,
Password: config.App.Cache.Redis.Password,
DB: config.App.Cache.Redis.DB,
},
),

psqlRepository: psqladapter.New(psqladapter.PSQLConfig{
Host: config.App.Datastore.PSQL.Host,
Port: config.App.Datastore.PSQL.Port,
Username: config.App.Datastore.PSQL.Username,
Password: config.App.Datastore.PSQL.Password,
DB: config.App.Datastore.PSQL.DB,
}),
}
}

// AppRepository struct would need to be updated to include new repository types
type AppRepository struct {
cacheRepository repository.CacheRepository
psqlRepository repository.PSQLRepository
}

func (a *AppRepository) CacheRepository() repository.CacheRepository {
return a.cacheRepository
}

func (a *AppRepository) PSQLRepository() repository.PSQLRepository {
return a.psqlRepository
}
func (a *AppRepository) GetBookRepository() repository.BookRepository {
return nil
return pgsqlrepository.NewBookRepository(a.psqlRepository)
}
27 changes: 27 additions & 0 deletions examples/books-api/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ type Config struct {
Port int `mapstructure:"port"`
Fiber FiberConfig `mapstructure:"fiber"`
Debug Debugging `mapstructure:"debug"`

Cache Cache `mapstructure:"cache"`

Datastore Datastore `mapstructure:"datastore"`
}

type Debugging struct {
Expand All @@ -29,6 +33,29 @@ type FiberConfig struct {
EnableSplittingOnParsers bool `mapstructure:"enable_splitting_on_parsers"`
}

type Cache struct {
Redis RedisConfig `mapstructure:"redis"`
}

type RedisConfig struct {
Addr string `mapstructure:"addr"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
DB int `mapstructure:"db"`
}

type Datastore struct {
PSQL PSQLConfig `mapstructure:"psql"`
}

type PSQLConfig struct {
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
DB string `mapstructure:"db"`
}

func LoadConfig() error {
viper.SetConfigName("config")
viper.AddConfigPath(".")
Expand Down
12 changes: 12 additions & 0 deletions examples/books-api/config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,16 @@ app:
fiber:
enable_print_routes: true
enable_splitting_on_parsers: true
cache:
redis:
addr: localhost:6379
username:
password:
db: 0
datastore:
psql:
host: localhost
port: 5432
username: myapp
password: myapp
db: myapp
27 changes: 27 additions & 0 deletions examples/books-api/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
version: "3.9"
services:
redis:
image: redis:7-alpine3.20
container_name: redis_dev
ports:
- "6379:6379"
command: ["redis-server"]
networks:
- dev-network
postgres:
image: postgres:15-alpine
container_name: postgres_dev
environment:
POSTGRES_USER: myapp
POSTGRES_PASSWORD: myapp
POSTGRES_DB: myapp
ports:
- "5432:5432"
networks:
- dev-network
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
networks:
dev-network:
Loading
Loading