- Microservices Architecture - Independently deployable services
- Service Discovery - Automatic service registration with Netflix Eureka
- API Gateway - Centralized routing with Spring Cloud Gateway
- Event-Driven - Asynchronous communication with Apache Kafka
- Caching - High-performance caching with Redis
- GraphQL - Flexible data querying with Netflix DGS
- JWT Authentication - Secure user authentication
- Containerization - Easy deployment with Docker
- User registration and authentication
- Product catalog and category management
- Advanced product search and filtering
- Shopping cart management (Redis-backed)
- Order creation and tracking
- Email notifications (Kafka-driven)
- Multiple address management
- Featured products
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CLIENTS β
β (Web App, Mobile App, Third Party) β
βββββββββββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β API GATEWAY β
β (Spring Cloud Gateway) β
β Port: 8080 β
βββββββββββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββΌββββββββββββββββββ
β β β
βΌ βΌ βΌ
ββββββββββββββββββββββββ ββββββββββββββββββββββββ ββββββββββββββββββββββββ
β DISCOVERY SERVER β β REST APIs β β GraphQL β
β (Eureka) β β β β (Netflix DGS) β
β Port: 8761 β β β β β
ββββββββββββββββββββββββ ββββββββββββββββββββββββ ββββββββββββββββββββββββ
β
βββββββββββββββ¬ββββββββββββββββΌββββββββββββββββ¬ββββββββββββββ
β β β β β
βΌ βΌ βΌ βΌ βΌ
βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ
β USER β β PRODUCT β β CART β β ORDER β βNOTIFICATION β
β SERVICE β β SERVICE β β SERVICE β β SERVICE β β SERVICE β
β Port: 8081 β β Port: 8082 β β Port: 8083β β Port: 8084 β β Port: 8085 β
ββββββββ¬βββββββ ββββββββ¬βββββββ ββββββββ¬βββββββ ββββββββ¬βββββββ ββββββββ¬βββββββ
β β β β β
βΌ βΌ βΌ β β
βββββββββββββββ βββββββββββββββ βββββββββββββββ β β
β MongoDB β β MongoDB β β Redis β β β
β users β β products β β carts β β β
βββββββββββββββ βββββββββββββββ βββββββββββββββ β |
β β β
βΌ βΌ β
βββββββββββββββ βββββββββββββββ β
β Redis β β MongoDB β β
β (Cache) β β orders β β
βββββββββββββββ ββββββββ¬βββββββ β
β β
βΌ βΌ
βββββββββββββββββββββββββββββ
β Apache Kafka β
β (Event Streaming) β
βββββββββββββββββ¬ββββββββββββ
β
βΌ
βββββββββββββββ
β MongoDB β
βnotificationsβ
βββββββββββββββ
βββββββββββββββ order-created βββββββββββββββββββ
β ORDER β βββββββββββββββββββΆ β |
β SERVICE β order-updated β NOTIFICATION β
β β βββββββββββββββββββΆ β SERVICE β
β β order-cancelled β β
β β βββββββββββββββββββΆ β β
βββββββββββββββ βββββββββββββββββββ
β
βΌ
βββββββββββββββ
β Email β
β Service β
βββββββββββββββ
| Port | 8761 |
| Description | Service discovery and registration center |
| Dashboard | http://localhost:8761 |
| Port | 8080 |
| Description | Centralized routing and load balancing |
| Technology | Spring Cloud Gateway |
| Port | 8081 |
| Database | MongoDB (blink_users) |
| Description | User management and JWT authentication |
Features:
- User registration and login
- JWT token management
- Profile management
- Multiple address management
| Port | 8082 |
| Database | MongoDB (blink_products) |
| Cache | Redis |
| Description | Product and category management |
Features:
- Product CRUD operations
- Category hierarchy
- Advanced search and filtering
- Redis caching
- Stock management
| Port | 8083 |
| Database | Redis |
| Description | Shopping cart management |
Features:
- Fast cart operations (Redis-backed)
- Automatic cart expiration (TTL)
- Stock validation
- Product info synchronization
| Port | 8084 |
| Database | MongoDB (blink_orders) |
| Message Broker | Apache Kafka |
| Description | Order management |
Features:
- Order creation
- Order status tracking
- Automatic stock deduction
- Kafka event publishing
- Order cancellation and refunds
| Port | 8085 |
| Database | MongoDB (blink_notifications) |
| Message Broker | Apache Kafka (Consumer) |
| Description | Notification management |
Features:
- Kafka event consumption
- Email notifications (Thymeleaf templates)
- Notification history
- Read/unread tracking
| Technology | Version | Description |
|---|---|---|
| Java | 21 | Primary programming language |
| Spring Boot | 3.3.5 | Application framework |
| Spring Cloud | 2023.0.3 | Microservices infrastructure |
| Spring Security | 6.x | Security framework |
| Netflix DGS | 9.1.3 | GraphQL framework |
| Technology | Version | Usage |
|---|---|---|
| MongoDB | 7.0 | Primary database |
| Redis | 7.x | Cache & Session store |
| Technology | Version | Usage |
|---|---|---|
| Apache Kafka | 7.5.0 | Event streaming |
| Zookeeper | 7.5.0 | Kafka coordination |
| Technology | Version | Usage |
|---|---|---|
| Docker | 24.x | Containerization |
| Docker Compose | 2.x | Container orchestration |
| Kubernetes | 1.28+ | Container orchestration |
| Minikube | 1.32+ | Local Kubernetes cluster |
| Technology | Usage |
|---|---|
| Lombok | Boilerplate code reduction |
| MapStruct | Object mapping |
| Thymeleaf | Email templates |
| JWT (jjwt) | Token management |
- Docker: 24.x or higher
- Docker Compose: 2.x or higher
- Java: 21 (for development only)
- Maven: 3.9.x (for development only)
- Git: 2.x
Ensure the following ports are available:
8080, 8081, 8082, 8083, 8084, 8085 (Application services)
8761 (Eureka)
8088, 8089, 8090 (Management UIs)
27017 (MongoDB)
6379 (Redis)
9092, 29092 (Kafka)
2181 (Zookeeper)
# 1. Clone the repository
git clone https://github.com/tarkanbatar/blink.git
cd blink
# 2. Start all services
docker-compose up --build -d
# 3. Wait for services to start (2-3 minutes)
docker-compose ps
# 4. Check Eureka Dashboard
open http://localhost:8761git clone https://github.com/tarkanbatar/blink.git
cd blink# Create .env file
cat > .env << EOF
MONGO_ROOT_USERNAME=root
MONGO_ROOT_PASSWORD=rootpassword
REDIS_PASSWORD=redispassword
JWT_SECRET=mySecretKeyForJWTTokenGenerationMinimum256BitsLong123456789
EOF# Build and start all services
docker-compose up --build -d
# Follow logs
docker-compose logs -f# Check container status
docker-compose ps
# Health check
curl http://localhost:8761/actuator/health
curl http://localhost:8080/actuator/healthTo run only infrastructure services in Docker and application services from IDE:
# Start only infrastructure (MongoDB, Redis, Kafka)
docker-compose -f docker-compose.dev.yml up -d
# Start services from IDE or manually:
cd user-service && ./mvnw spring-boot:run &
cd product-service && ./mvnw spring-boot:run &
cd cart-service && ./mvnw spring-boot:run &
cd order-service && ./mvnw spring-boot:run &
cd notification-service && ./mvnw spring-boot:run &# Stop services
docker-compose stop
# Stop and remove containers
docker-compose down
# Remove everything including volumes (WARNING: Data will be lost!)
docker-compose down -v --rmi allPrerequisites:
- Minikube with Docker driver and
ingressaddon enabled - kubectl and Docker available in the shell
- Suggested: at least 4 CPUs, 8 GB RAM, and 20 GB free disk space
Steps:
- Start Minikube with ingress enabled:
minikube start --driver=docker --cpus=4 --memory=8192 --addons=ingress- Build images inside the Minikube Docker daemon and deploy everything:
cd C:\Users\USERNANE\Workspace\blink
minikube -p minikube docker-env --shell powershell | Invoke-Expression
.\k8s\deploy-minikube.ps1The script builds all service images with the blink/<service>:latest tag (deployments use imagePullPolicy: Never), creates the blink namespace, applies required secrets/configs, deploys MongoDB, Redis, Kafka, all services, and the ingress.
- Map the ingress host to the Minikube IP:
minikube ip
# Add the output IP to C:\Windows\System32\drivers\etc\hosts
# <ip> api.blink.local- Verify and call the API:
kubectl get pods -n blink
kubectl get ingress -n blink
curl http://api.blink.local/api/productsCleanup:
kubectl delete namespace blinkhttp://localhost:8080/api
JWT Bearer token is used for authentication. Obtain a token via /api/auth/login endpoint.
# Header format
Authorization: Bearer <your_jwt_token>POST /api/auth/register
Content-Type: application/json
{
"email": "user@example.com",
"password": "Password123!",
"firstName": "John",
"lastName": "Doe",
"phone": "+1234567890"
}Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.. .",
"tokenType": "Bearer",
"expiresIn": 86400,
"user": {
"id": "6571a2b3c4d5e6f7a8b9c0d1",
"email": "user@example.com",
"firstName": "John",
"lastName": "Doe"
}
}POST /api/auth/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "Password123!"
}GET /api/users/me
Authorization: Bearer <token>PATCH /api/users/me
Authorization: Bearer <token>
Content-Type: application/json
{
"firstName": "Jane",
"lastName": "Doe",
"phone": "+0987654321"
}POST /api/users/me/addresses
Authorization: Bearer <token>
Content-Type: application/json
{
"title": "Home",
"addressLine1": "123 Main Street",
"addressLine2": "Apt 4B",
"city": "New York",
"state": "NY",
"country": "USA",
"zipCode": "10001",
"isDefault": true
}DELETE /api/users/me/addresses/{addressId}
Authorization: Bearer <token>PATCH /api/users/me/addresses/{addressId}/default
Authorization: Bearer <token>GET /api/products? page=0&size=20Response:
{
"content": [
{
"id": "6571a2b3c4d5e6f7a8b9c0d1",
"name": "iPhone 15 Pro",
"price": 999.99,
"discountedPrice": 899.99,
"discountPercentage": 10,
"inStock": true,
"brand": "Apple"
}
],
"currentPage": 0,
"totalPages": 10,
"totalElements": 200,
"size": 20
}GET /api/products/{id}GET /api/products/sku/{sku}POST /api/products/search
Content-Type: application/json
{
"keyword": "iPhone",
"categoryId": "electronics-id",
"minPrice": 500,
"maxPrice": 1500,
"brands": ["Apple", "Samsung"],
"inStock": true,
"featured": false,
"minRating": 4.0,
"sortBy": "price",
"sortDirection": "asc",
"page": 0,
"size": 20
}GET /api/products/featuredGET /api/products/category/{categoryId}? page=0&size=20POST /api/products
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"name": "iPhone 15 Pro",
"description": "Apple iPhone 15 Pro 256GB",
"sku": "IPHONE-15-PRO-256",
"price": 999.99,
"discountedPrice": 899.99,
"categoryId": "6571a2b3c4d5e6f7a8b9c0d1",
"stock": 100,
"brand": "Apple",
"images": [
"https://example.com/iphone15-1.jpg",
"https://example.com/iphone15-2.jpg"
],
"attributes": {
"color": "Titanium Black",
"storage": "256GB",
"ram": "8GB"
},
"featured": true
}PATCH /api/products/{id}
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"price": 949.99,
"stock": 150,
"featured": true
}PATCH /api/products/{id}/stock? quantity=100
Authorization: Bearer <admin_token>DELETE /api/products/{id}
Authorization: Bearer <admin_token>GET /api/categoriesGET /api/categories/rootGET /api/categories/{id}GET /api/categories/{id}/subcategoriesPOST /api/categories
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"name": "Electronics",
"description": "Electronic devices and accessories",
"parentId": null,
"imageUrl": "https://example.com/electronics.jpg",
"displayOrder": 1
}PUT /api/categories/{id}
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"name": "Electronics & Gadgets",
"description": "Updated description",
"displayOrder": 2
}DELETE /api/categories/{id}
Authorization: Bearer <admin_token>GET /api/cart
X-User-Id: user123Response:
{
"userId": "user123",
"items": [
{
"productId": "6571a2b3c4d5e6f7a8b9c0d1",
"productName": "iPhone 15 Pro",
"productImage": "https://example.com/iphone15.jpg",
"unitPrice": 899.99,
"quantity": 2,
"totalPrice": 1799.98
}
],
"totalItems": 2,
"totalPrice": 1799.98,
"empty": false,
"createdAt": "2024-12-05T10:30:00",
"updatedAt": "2024-12-05T14:45:00"
}POST /api/cart/items
X-User-Id: user123
Content-Type: application/json
{
"productId": "6571a2b3c4d5e6f7a8b9c0d1",
"quantity": 2
}PATCH /api/cart/items/{productId}
X-User-Id: user123
Content-Type: application/json
{
"quantity": 3
}DELETE /api/cart/items/{productId}
X-User-Id: user123DELETE /api/cart
X-User-Id: user123POST /api/orders
X-User-Id: user123
Content-Type: application/json
{
"shippingAddress": {
"fullName": "John Doe",
"phone": "+1234567890",
"addressLine1": "123 Main Street",
"addressLine2": "Apt 4B",
"city": "New York",
"state": "NY",
"country": "USA",
"zipCode": "10001"
},
"paymentMethod": "CREDIT_CARD",
"notes": "Please leave at the door"
}Response:
{
"id": "6571a2b3c4d5e6f7a8b9c0d1",
"orderNumber": "ORD-20241205-A1B2C",
"userId": "user123",
"items": [... ],
"totalItems": 2,
"status": "PENDING",
"statusDescription": "Pending",
"subtotal": 1799.98,
"shippingCost": 9.99,
"tax": 162.00,
"discount": 0,
"totalAmount": 1971.97,
"paymentMethod": "CREDIT_CARD",
"cancellable": true,
"createdAt": "2024-12-05T14:30:00"
}GET /api/orders/{orderId}GET /api/orders/number/{orderNumber}GET /api/orders/my-orders? page=0&size=10
X-User-Id: user123GET /api/orders/status/{status}? page=0&size=10
Authorization: Bearer <admin_token>Available Statuses:
PENDING- Order created, awaiting paymentCONFIRMED- Payment received, order confirmedPROCESSING- Order is being preparedSHIPPED- Order shippedDELIVERED- Order deliveredCANCELLED- Order cancelledREFUNDED- Order refunded
PATCH /api/orders/{orderId}/status
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"status": "SHIPPED",
"trackingNumber": "TR123456789",
"note": "Shipped via FedEx"
}POST /api/orders/{orderId}/cancel? reason=Changed my mind
X-User-Id: user123GET /api/notifications? page=0&size=20
X-User-Id: user123Response:
[
{
"id": "6571a2b3c4d5e6f7a8b9c0d1",
"userId": "user123",
"type": "ORDER_CREATED",
"typeDescription": "Order Created",
"channel": "EMAIL",
"status": "SENT",
"title": "Order Created - ORD-20241205-A1B2C",
"content": "Your order has been created successfully.",
"orderId": "order123",
"orderNumber": "ORD-20241205-A1B2C",
"sentAt": "2024-12-05T14:30:00",
"readAt": null,
"createdAt": "2024-12-05T14:30:00"
}
]GET /api/notifications/unread-count
X-User-Id: user123Response:
{
"unreadCount": 5
}GET /api/notifications/{id}PATCH /api/notifications/{id}/readPATCH /api/notifications/read-all
X-User-Id: user123POST /graphql
http://localhost:8080/graphiql
query GetProducts {
products(page: 0, size: 10) {
content {
id
name
description
price
discountedPrice
discountPercentage
inStock
brand
categoryName
images
rating
reviewCount
}
totalElements
totalPages
currentPage
first
last
}
}query GetProduct($id: ID!) {
product(id: $id) {
id
name
description
sku
price
discountedPrice
stock
brand
categoryId
categoryName
attributes {
key
value
}
images
rating
reviewCount
active
featured
createdAt
}
}query SearchProducts {
searchProducts(filter: {
keyword: "iPhone"
minPrice: 500
maxPrice: 1500
inStock: true
sortBy: "price"
sortDirection: "asc"
page: 0
size: 10
}) {
content {
id
name
price
brand
inStock
}
totalElements
totalPages
}
}query GetFeaturedProducts {
featuredProducts {
id
name
price
discountedPrice
images
brand
}
}query GetCategories {
categories {
id
name
description
parentId
imageUrl
displayOrder
subCategories {
id
name
}
}
}query GetRootCategories {
rootCategories {
id
name
description
subCategories {
id
name
subCategories {
id
name
}
}
}
}query GetCart($userId: String!) {
cart(userId: $userId) {
userId
items {
productId
productName
productImage
unitPrice
quantity
totalPrice
}
totalItems
totalPrice
empty
createdAt
updatedAt
}
}query GetMyOrders($userId: String!) {
myOrders(userId: $userId, page: 0, size: 10) {
id
orderNumber
status
statusDescription
totalAmount
totalItems
trackingNumber
estimatedDeliveryDate
cancellable
createdAt
items {
productName
quantity
unitPrice
totalPrice
}
shippingAddress {
fullName
city
country
}
}
}query GetOrder($id: ID!) {
order(id: $id) {
id
orderNumber
userId
userEmail
status
statusDescription
items {
productId
productName
productImage
sku
unitPrice
quantity
totalPrice
}
shippingAddress {
fullName
phone
addressLine1
addressLine2
city
state
country
zipCode
}
subtotal
shippingCost
tax
discount
totalAmount
paymentMethod
trackingNumber
estimatedDeliveryDate
cancellable
createdAt
}
}mutation AddToCart($userId: String!, $productId: String!, $quantity: Int!) {
addToCart(userId: $userId, input: {
productId: $productId
quantity: $quantity
}) {
userId
items {
productId
productName
quantity
totalPrice
}
totalItems
totalPrice
}
}mutation UpdateCartQuantity($userId: String!, $productId: String!, $quantity: Int!) {
updateCartItemQuantity(
userId: $userId
productId: $productId
quantity: $quantity
) {
userId
items {
productId
quantity
totalPrice
}
totalPrice
}
}mutation RemoveFromCart($userId: String!, $productId: String!) {
removeFromCart(userId: $userId, productId: $productId) {
userId
items {
productId
productName
}
totalItems
totalPrice
}
}mutation ClearCart($userId: String!) {
clearCart(userId: $userId)
}mutation CreateOrder($userId: String!) {
createOrder(
userId: $userId
input: {
shippingAddress: {
fullName: "John Doe"
phone: "+1234567890"
addressLine1: "123 Main Street"
city: "New York"
state: "NY"
country: "USA"
zipCode: "10001"
}
paymentMethod: "CREDIT_CARD"
notes: "Please leave at the door"
}
) {
id
orderNumber
status
totalAmount
items {
productName
quantity
unitPrice
}
}
}mutation UpdateOrderStatus($orderId: ID!) {
updateOrderStatus(
orderId: $orderId
input: {
status: SHIPPED
trackingNumber: "TR123456789"
}
) {
id
orderNumber
status
statusDescription
trackingNumber
}
}mutation CancelOrder($orderId: ID!) {
cancelOrder(orderId: $orderId, reason: "Changed my mind") {
id
orderNumber
status
statusDescription
cancellationReason
}
}mutation CreateProduct {
createProduct(input: {
name: "MacBook Pro 16"
description: "Apple MacBook Pro 16-inch M3 Pro"
sku: "MACBOOK-PRO-16-M3"
price: 2499.99
categoryId: "category-id"
stock: 50
brand: "Apple"
images: ["https://example.com/macbook. jpg"]
attributes: [
{ key: "processor", value: "M3 Pro" }
{ key: "ram", value: "18GB" }
{ key: "storage", value: "512GB" }
]
featured: true
}) {
id
name
sku
price
stock
}
}mutation CreateCategory {
createCategory(input: {
name: "Laptops"
description: "Laptop computers"
parentId: "electronics-category-id"
displayOrder: 1
}) {
id
name
parentId
}
}#!/bin/bash
echo "Checking service health..."
echo ""
services=(
"8761: Discovery Server"
"8080:API Gateway"
"8081:User Service"
"8082:Product Service"
"8083:Cart Service"
"8084:Order Service"
"8085:Notification Service"
)
for service in "${services[@]}"; do
port="${service%%:*}"
name="${service##*:}"
status=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:$port/actuator/health)
if [ "$status" == "200" ]; then
echo "$name (port $port): Healthy"
else
echo "$name (port $port): Unhealthy (HTTP $status)"
fi
done# Run tests for all services
./mvnw test
# Run tests for specific service
cd user-service && ./mvnw test
cd product-service && ./mvnw test| Service | URL | Credentials |
|---|---|---|
| Eureka Dashboard | http://localhost:8761 | - |
| Mongo Express | http://localhost:8088 | admin / admin123 |
| Redis Commander | http://localhost:8089 | - |
| Kafka UI | http://localhost:8090 | - |
# All services logs
docker-compose logs -f
# Specific service logs
docker-compose logs -f user-service
docker-compose logs -f order-service
docker-compose logs -f notification-service
# Last 100 lines
docker-compose logs --tail=100 -f# CPU and Memory usage
docker stats
# Disk usage
docker system df
# View specific container resources
docker stats blink-user-service# Restart a specific service
docker-compose restart user-service
# Rebuild and restart a service
docker-compose up --build -d user-service
# View container processes
docker-compose top
# Execute command in container
docker-compose exec user-service shblink-microservices/
β
βββ π discovery-server/ # Eureka Server
β βββ src/
β β βββ main/
β β βββ java/
β β βββ resources/
β β βββ application.yml
β β βββ application-docker.yml
β βββ Dockerfile
β βββ . dockerignore
β βββ pom.xml
β
βββ π api-gateway/ # Spring Cloud Gateway
β βββ src/
β βββ Dockerfile
β βββ pom.xml
β
βββ π user-service/ # User Management
β βββ src/
β β βββ main/
β β βββ java/
β β β βββ com/blink/user/
β β β βββ config/
β β β β βββ SecurityConfig. java
β β β β βββ MongoConfig.java
β β β βββ controller/
β β β β βββ AuthController.java
β β β β βββ UserController.java
β β β βββ datafetcher/
β β β β βββ UserDataFetcher.java
β β β βββ dto/
β β β β βββ request/
β β β β βββ response/
β β β βββ exception/
β β β βββ model/
β β β β βββ User.java
β β β β βββ Address.java
β β β βββ repository/
β β β βββ security/
β β β β βββ JwtService.java
β β β β βββ JwtAuthenticationFilter.java
β β β βββ service/
β β βββ resources/
β β βββ application.yml
β β βββ application-docker.yml
β β βββ schema/
β β βββ schema.graphqls
β βββ Dockerfile
β βββ pom.xml
β
βββ π product-service/ # Product Catalog
β βββ src/
β βββ Dockerfile
β βββ pom.xml
β
βββ π cart-service/ # Shopping Cart
β βββ src/
β βββ Dockerfile
β βββ pom.xml
β
βββ π order-service/ # Order Management
β βββ src/
β β βββ main/
β β βββ java/
β β βββ com/blink/order/
β β βββ client/
β β β βββ CartServiceClient.java
β β β βββ ProductServiceClient.java
β β β βββ UserServiceClient.java
β β βββ event/
β β β βββ OrderEvent.java
β β β βββ OrderEventPublisher.java
β β βββ ...
β βββ Dockerfile
β βββ pom. xml
β
βββ π notification-service/ # Notifications
β βββ src/
β β βββ main/
β β βββ java/
β β β βββ com/blink/notification/
β β β βββ consumer/
β β β β βββ OrderEventConsumer.java
β β β βββ template/
β β β β βββ EmailTemplateService.java
β β β βββ ...
β β βββ resources/
β β βββ templates/
β β βββ order-created.html
β β βββ order-shipped.html
β β βββ ...
β βββ Dockerfile
β βββ pom. xml
β
βββ π docker-compose.yml # Production compose
βββ π docker-compose. dev.yml # Development compose
βββ π . env. example # Environment example
βββ π . gitignore
βββ π LICENSE
βββ π README.md
This project is licensed under the MIT License. See the LICENSE file for details.
MIT License
Copyright (c) 2024 Tarkan Batar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Tarkan Batar
- GitHub: @tarkanbatar
- LinkedIn: Tarkan Batar