A (WIP) RESTful API and CLI client for an RPG shop inventory system, built with Go and PostgreSQL. The API handles all the business logic and database operations. The CLI client provides a terminal interface for browsing and purchasing items.
- Go: HTTP server and CLI client
- PostgreSQL: persistent storage
- goose: database migrations
- sqlc: type-safe SQL query generation
- Browse shop inventory with item names, prices, and current quantity
- Buy items by index number (stock decreases on purchase, fails if out of stock)
- Restock items by index with a specified quantity
- Full REST API with JSON responses
- Register and log in with a name and password
- Password hashing using argon2id
rpg-shop/
├── main.go # Server entry point
├── server.go # Server struct and helpers
├── handler_items.go # HTTP handlers
├── items.go # Item type definition
├── cmd/
│ └── shop/
│ └── main.go # CLI client entry point
├── internal/
│ └── auth/ # user authentication stuff
│ └── database/ # sqlc generated code
├── sql/
│ ├── queries/ # SQL queries
│ └── schema/ # goose migrations
└── sqlc.yaml
- Go 1.21+
- PostgreSQL
- goose:
go install github.com/pressly/goose/v3/cmd/goose@latest - sqlc:
go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest
- Clone the repository
git clone https://github.com/LunarDrift/rpg-shop
cd rpg-shop- Create the database
createdb rpg_shop- Run migrations
goose -dir sql/schema postgres "postgres://username:password@localhost/rpg_shop?sslmode=disable" up- Seed the database
psql rpg_shop < sql/seed.sql-
Set up the environment variables
- Copy and rename the
.env.examplefile to.envand enter your database name:
cp .env.example .env
# Generate a secure JWT secret openssl rand -hex 64# If your Postgres user has a password: DB_URL=postgres://username:password@localhost/rpg_shop?sslmode=disable # If no password required: DB_URL=postgres://localhost/rpg_shop?sslmode=disable JWT_TOKEN=your_jwt_secret
- Copy and rename the
-
Install dependencies
go mod tidygo run .The server starts on http://localhost:8080
In a separate terminal:
# Browse all items in the shop
go run ./cmd/shop browse
# Register a new user (starts with 500g)
go run ./cmd/shop register <name> <password>
# Log in
go run ./cmd/shop login <name> <password>
# Buy an item by its index number and optional quantity
go run ./cmd/shop buy 2 5
# Show the current user and balance
go run ./cmd/shop whoami
# Explore and gain money
go run ./cmd/shop explore
# Restock an item (shopkeeper/admin)
go run ./cmd/shop/restock 2 10
# Log out
go run ./cmd/shop logout| Method | Endpoint | Description |
|---|---|---|
| GET | /health |
Health check |
| GET | /items |
List all items |
| GET | /items/{id} |
Get item by ID |
| POST | /items |
Create a new item (requires admin privelages) |
| POST | /items/buy/{id} |
Buy an item |
| PATCH | /items/restock/{id} |
Restock an item (requires admin privelages) |
| DELETE | /items/{id} |
Delete an item (requires admin privelages) |
| POST | /users |
Register a new user |
| POST | /users/login |
Log in to a registered user with name and password |
| GET | /users |
Get a user by name or list all users if no name provided |
| GET | /users/{id} |
Get a user by ID |
| PATCH | users/earn |
Gain a random amount (10-100) of gold |
To add items directly via psql:
psql rpg_shopINSERT INTO items (name, description, price, quantity)
VALUES
('Iron Sword', 'A sturdy blade forged from iron', 100, 5),
('Health Potion', 'Restores 50 HP', 25, 10),
('Magic Staff', 'Channels arcane energy', 200, 2);