feat: prepare all services for production deployment

Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-03-06 02:28:24 +00:00
parent b1953ea883
commit 9085e7a023
37 changed files with 668 additions and 13 deletions

4
pitstop/.dockerignore Normal file
View File

@@ -0,0 +1,4 @@
.git
.gitignore
README.md
.DS_Store

2
pitstop/.env.example Normal file
View File

@@ -0,0 +1,2 @@
# Server
PORT=8080

15
pitstop/Dockerfile Normal file
View File

@@ -0,0 +1,15 @@
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o pitstop .
FROM alpine:3.19
RUN apk --no-cache add ca-certificates
WORKDIR /app
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
COPY --from=builder /app/pitstop .
USER appuser
EXPOSE 8080
CMD ["./pitstop"]

View File

@@ -3,3 +3,30 @@ module pitstop
go 1.21 go 1.21
require github.com/gin-gonic/gin v1.9.1 require github.com/gin-gonic/gin v1.9.1
require (
github.com/bytedance/sonic v1.9.1 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gin-contrib/sse v0.1.0 // 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/goccy/go-json v0.10.2 // 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/mattn/go-isatty v0.0.19 // 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/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/crypto v0.9.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

86
pitstop/go.sum Normal file
View File

@@ -0,0 +1,86 @@
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@@ -13,9 +13,12 @@ func main() {
r := gin.Default() r := gin.Default()
r.GET("/health", func(c *gin.Context) { healthHandler := func(c *gin.Context) {
c.JSON(200, gin.H{"status": "healthy", "service": "PitStop"}) c.JSON(200, gin.H{"status": "healthy", "service": "PitStop", "version": "1.0.0"})
}) }
r.GET("/health", healthHandler)
r.GET("/api/health", healthHandler)
r.GET("/", func(c *gin.Context) { r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{ c.JSON(200, gin.H{

5
roadchain/.dockerignore Normal file
View File

@@ -0,0 +1,5 @@
target
.git
.gitignore
README.md
.DS_Store

5
roadchain/.env.example Normal file
View File

@@ -0,0 +1,5 @@
# Server
PORT=8080
# CORS
CORS_ORIGIN=https://your-domain.com

18
roadchain/Dockerfile Normal file
View File

@@ -0,0 +1,18 @@
FROM rust:1.75-slim AS builder
WORKDIR /app
RUN apt-get update && apt-get install -y pkg-config libssl-dev && rm -rf /var/lib/apt/lists/*
COPY Cargo.toml ./
RUN mkdir src && echo "fn main() {}" > src/main.rs
RUN cargo build --release && rm -f target/release/deps/roadchain*
COPY src ./src
RUN cargo build --release
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
WORKDIR /app
RUN groupadd --system appgroup && useradd --system --gid appgroup appuser
COPY --from=builder /app/target/release/roadchain .
RUN chown appuser:appgroup ./roadchain
USER appuser
EXPOSE 8080
CMD ["./roadchain"]

View File

@@ -5,6 +5,7 @@ use sha2::{Sha256, Digest};
use std::sync::Mutex; use std::sync::Mutex;
use chrono::Utc; use chrono::Utc;
use uuid::Uuid; use uuid::Uuid;
use std::env;
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
struct Block { struct Block {
@@ -62,8 +63,9 @@ async fn root() -> impl Responder {
#[actix_web::main] #[actix_web::main]
async fn main() -> std::io::Result<()> { async fn main() -> std::io::Result<()> {
let port = std::env::var("PORT").unwrap_or_else(|_| "8080".to_string()); let port = env::var("PORT").unwrap_or_else(|_| "8080".to_string());
let addr = format!("0.0.0.0:{}", port); let addr = format!("0.0.0.0:{}", port);
let allowed_origin = env::var("CORS_ORIGIN").unwrap_or_else(|_| "http://localhost:3000".to_string());
let genesis = Block::new(0, "Genesis".to_string(), "0".to_string()); let genesis = Block::new(0, "Genesis".to_string(), "0".to_string());
let app_state = web::Data::new(AppState { let app_state = web::Data::new(AppState {
@@ -73,10 +75,16 @@ async fn main() -> std::io::Result<()> {
println!("RoadChain running on port {}", port); println!("RoadChain running on port {}", port);
HttpServer::new(move || { HttpServer::new(move || {
let cors = Cors::default()
.allowed_origin(&allowed_origin)
.allowed_methods(vec!["GET", "POST"])
.allowed_headers(vec!["Content-Type", "Authorization"])
.max_age(3600);
App::new() App::new()
.wrap(Cors::default().allow_any_origin()) .wrap(cors)
.app_data(app_state.clone()) .app_data(app_state.clone())
.route("/health", web::get().to(health_check)) .route("/health", web::get().to(health_check))
.route("/api/health", web::get().to(health_check))
.route("/", web::get().to(root)) .route("/", web::get().to(root))
}) })
.bind(&addr)? .bind(&addr)?

12
roadcoin/.dockerignore Normal file
View File

@@ -0,0 +1,12 @@
__pycache__
*.pyc
*.pyo
.env
.venv
venv
.git
.gitignore
README.md
*.egg-info
dist
.DS_Store

6
roadcoin/.env.example Normal file
View File

@@ -0,0 +1,6 @@
# Server
PORT=8000
APP_ENV=production
# CORS (comma-separated list of allowed origins)
CORS_ORIGINS=https://your-domain.com

10
roadcoin/Dockerfile Normal file
View File

@@ -0,0 +1,10 @@
FROM python:3.11-slim
WORKDIR /app
RUN addgroup --system appgroup && adduser --system --ingroup appgroup appuser
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY --chown=appuser:appgroup . .
USER appuser
EXPOSE 8000
ENV PORT=8000
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]

View File

@@ -11,11 +11,13 @@ app = FastAPI(
version="1.0.0" version="1.0.0"
) )
allowed_origins = os.getenv("CORS_ORIGINS", "http://localhost:3000").split(",")
app.add_middleware( app.add_middleware(
CORSMiddleware, CORSMiddleware,
allow_origins=["*"], allow_origins=allowed_origins,
allow_methods=["*"], allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["*"], allow_headers=["Content-Type", "Authorization"],
) )
class Campaign(BaseModel): class Campaign(BaseModel):
@@ -66,6 +68,15 @@ async def health():
"timestamp": datetime.utcnow().isoformat() "timestamp": datetime.utcnow().isoformat()
} }
@app.get("/api/health")
async def api_health():
return {
"status": "healthy",
"service": "RoadCoin",
"version": "1.0.0",
"timestamp": datetime.utcnow().isoformat()
}
@app.get("/") @app.get("/")
async def root(): async def root():
return { return {

10
roadmap/.dockerignore Normal file
View File

@@ -0,0 +1,10 @@
node_modules
.next
.env
.env.local
*.log
npm-debug.log*
.DS_Store
.git
.gitignore
README.md

10
roadmap/.env.example Normal file
View File

@@ -0,0 +1,10 @@
# Server
PORT=3000
NODE_ENV=production
# Authentication (Clerk)
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=your_clerk_publishable_key_here
CLERK_SECRET_KEY=your_clerk_secret_key_here
# Deployment
DEPLOYMENT_TARGET=production

23
roadmap/Dockerfile Normal file
View File

@@ -0,0 +1,23 @@
FROM node:20-alpine AS base
WORKDIR /app
FROM base AS deps
COPY package.json package-lock.json* ./
RUN npm ci
FROM base AS builder
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
FROM base AS runner
ENV NODE_ENV=production
RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]

View File

@@ -0,0 +1,178 @@
'use client'
import Link from 'next/link'
import { useEffect, useState } from 'react'
interface Project {
id: string
name: string
description: string
status: string
priority: string
tasks: number
completedTasks: number
team: string[]
createdAt: string
}
interface Task {
id: string
projectId: string
title: string
status: string
priority: string
assignee: string | null
dueDate: string | null
}
interface Stats {
totalProjects: number
inProgress: number
totalTasks: number
completedTasks: number
}
export default function Dashboard() {
const [projects, setProjects] = useState<Project[]>([])
const [tasks, setTasks] = useState<Task[]>([])
const [stats, setStats] = useState<Stats>({ totalProjects: 0, inProgress: 0, totalTasks: 0, completedTasks: 0 })
const [loading, setLoading] = useState(true)
useEffect(() => {
Promise.all([
fetch('/api/projects').then(r => r.json()),
fetch('/api/tasks').then(r => r.json()),
]).then(([projectsData, tasksData]) => {
const p: Project[] = projectsData.data || []
const t: Task[] = tasksData.data || []
setProjects(p)
setTasks(t)
setStats({
totalProjects: p.length,
inProgress: p.filter(x => x.status === 'in_progress').length,
totalTasks: t.length,
completedTasks: t.filter(x => x.status === 'completed').length,
})
setLoading(false)
}).catch(() => setLoading(false))
}, [])
return (
<div className="min-h-screen bg-gradient-to-br from-blackroad-900 via-purple-900 to-blackroad-900 p-6">
<div className="max-w-6xl mx-auto">
<div className="flex items-center justify-between mb-8">
<div>
<h1 className="text-3xl font-bold text-white">🗺 RoadMap Dashboard</h1>
<p className="text-gray-400 mt-1">Track your projects and tasks</p>
</div>
<Link href="/" className="text-gray-400 hover:text-white transition text-sm">
Back to Home
</Link>
</div>
{/* Stats */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8">
<StatCard label="Total Projects" value={stats.totalProjects} icon="📁" />
<StatCard label="In Progress" value={stats.inProgress} icon="🔄" />
<StatCard label="Total Tasks" value={stats.totalTasks} icon="✅" />
<StatCard label="Completed" value={stats.completedTasks} icon="🎯" />
</div>
{loading ? (
<div className="text-center text-gray-400 py-12">Loading...</div>
) : (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{/* Projects */}
<div className="bg-white/10 backdrop-blur-lg rounded-lg p-6 border border-white/20">
<h2 className="text-xl font-bold text-white mb-4">Projects</h2>
{projects.length === 0 ? (
<p className="text-gray-400">No projects yet.</p>
) : (
<ul className="space-y-3">
{projects.map(project => (
<li key={project.id} className="bg-white/5 rounded-lg p-4">
<div className="flex items-center justify-between mb-1">
<span className="font-semibold text-white">{project.name}</span>
<StatusBadge status={project.status} />
</div>
<p className="text-gray-400 text-sm mb-2">{project.description}</p>
<div className="flex items-center gap-2">
<div className="flex-1 bg-white/10 rounded-full h-1.5">
<div
className="bg-blackroad-500 h-1.5 rounded-full"
style={{ width: project.tasks > 0 ? `${(project.completedTasks / project.tasks) * 100}%` : '0%' }}
/>
</div>
<span className="text-gray-400 text-xs">{project.completedTasks}/{project.tasks}</span>
</div>
</li>
))}
</ul>
)}
</div>
{/* Recent Tasks */}
<div className="bg-white/10 backdrop-blur-lg rounded-lg p-6 border border-white/20">
<h2 className="text-xl font-bold text-white mb-4">Recent Tasks</h2>
{tasks.length === 0 ? (
<p className="text-gray-400">No tasks yet.</p>
) : (
<ul className="space-y-3">
{tasks.slice(0, 6).map(task => (
<li key={task.id} className="bg-white/5 rounded-lg p-3 flex items-start gap-3">
<span className="text-lg mt-0.5">{task.status === 'completed' ? '✅' : task.status === 'in_progress' ? '🔄' : '📋'}</span>
<div className="flex-1 min-w-0">
<div className="font-medium text-white text-sm truncate">{task.title}</div>
<div className="flex items-center gap-2 mt-1">
<PriorityBadge priority={task.priority} />
{task.assignee && <span className="text-gray-400 text-xs"> {task.assignee}</span>}
</div>
</div>
</li>
))}
</ul>
)}
</div>
</div>
)}
</div>
</div>
)
}
function StatCard({ label, value, icon }: { label: string; value: number; icon: string }) {
return (
<div className="bg-white/10 backdrop-blur-lg rounded-lg p-5 border border-white/20 text-center">
<div className="text-3xl mb-2">{icon}</div>
<div className="text-2xl font-bold text-white">{value}</div>
<div className="text-gray-400 text-sm">{label}</div>
</div>
)
}
function StatusBadge({ status }: { status: string }) {
const colors: Record<string, string> = {
in_progress: 'bg-blue-500/30 text-blue-300',
completed: 'bg-green-500/30 text-green-300',
planning: 'bg-yellow-500/30 text-yellow-300',
on_hold: 'bg-red-500/30 text-red-300',
}
return (
<span className={`text-xs px-2 py-0.5 rounded-full ${colors[status] || 'bg-gray-500/30 text-gray-300'}`}>
{status.replace('_', ' ')}
</span>
)
}
function PriorityBadge({ priority }: { priority: string }) {
const colors: Record<string, string> = {
high: 'bg-red-500/30 text-red-300',
medium: 'bg-yellow-500/30 text-yellow-300',
low: 'bg-green-500/30 text-green-300',
}
return (
<span className={`text-xs px-1.5 py-0.5 rounded ${colors[priority] || 'bg-gray-500/30 text-gray-300'}`}>
{priority}
</span>
)
}

View File

@@ -3,6 +3,7 @@ const nextConfig = {
reactStrictMode: true, reactStrictMode: true,
poweredByHeader: false, poweredByHeader: false,
compress: true, compress: true,
output: 'standalone',
env: { env: {
DEPLOYMENT_TARGET: process.env.DEPLOYMENT_TARGET || 'production' DEPLOYMENT_TARGET: process.env.DEPLOYMENT_TARGET || 'production'
} }

8
roadside/.dockerignore Normal file
View File

@@ -0,0 +1,8 @@
node_modules
.env
*.log
npm-debug.log*
.DS_Store
.git
.gitignore
README.md

3
roadside/.env.example Normal file
View File

@@ -0,0 +1,3 @@
# Server
PORT=3000
NODE_ENV=production

10
roadside/Dockerfile Normal file
View File

@@ -0,0 +1,10 @@
FROM node:20-alpine
WORKDIR /app
RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 appuser
COPY package.json package-lock.json* ./
RUN npm ci --omit=dev
COPY --chown=appuser:nodejs . .
USER appuser
EXPOSE 3000
ENV NODE_ENV=production
CMD ["node", "server.js"]

View File

@@ -8,6 +8,10 @@ app.get('/health', (req, res) => {
res.json({ status: 'healthy', service: 'RoadSide', version: '1.0.0' }); res.json({ status: 'healthy', service: 'RoadSide', version: '1.0.0' });
}); });
app.get('/api/health', (req, res) => {
res.json({ status: 'healthy', service: 'RoadSide', version: '1.0.0' });
});
app.get('/', (req, res) => { app.get('/', (req, res) => {
res.json({ res.json({
name: 'RoadSide', name: 'RoadSide',

8
roadview/.dockerignore Normal file
View File

@@ -0,0 +1,8 @@
node_modules
.env
*.log
npm-debug.log*
.DS_Store
.git
.gitignore
README.md

3
roadview/.env.example Normal file
View File

@@ -0,0 +1,3 @@
# Server
PORT=3000
NODE_ENV=production

10
roadview/Dockerfile Normal file
View File

@@ -0,0 +1,10 @@
FROM node:20-alpine
WORKDIR /app
RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 appuser
COPY package.json package-lock.json* ./
RUN npm ci --omit=dev
COPY --chown=appuser:nodejs . .
USER appuser
EXPOSE 3000
ENV NODE_ENV=production
CMD ["node", "server.js"]

View File

@@ -8,6 +8,10 @@ app.get('/health', (req, res) => {
res.json({ status: 'healthy', service: 'RoadView', version: '1.0.0' }); res.json({ status: 'healthy', service: 'RoadView', version: '1.0.0' });
}); });
app.get('/api/health', (req, res) => {
res.json({ status: 'healthy', service: 'RoadView', version: '1.0.0' });
});
app.get('/', (req, res) => { app.get('/', (req, res) => {
res.json({ res.json({
name: 'RoadView', name: 'RoadView',

8
roadwork/.dockerignore Normal file
View File

@@ -0,0 +1,8 @@
node_modules
.env
*.log
npm-debug.log*
.DS_Store
.git
.gitignore
README.md

View File

@@ -2,3 +2,4 @@ PORT=3000
NODE_ENV=production NODE_ENV=production
MONGODB_URI=mongodb://localhost:27017/roadwork MONGODB_URI=mongodb://localhost:27017/roadwork
JWT_SECRET=your-secret-key-here JWT_SECRET=your-secret-key-here
CORS_ORIGIN=https://your-domain.com

10
roadwork/Dockerfile Normal file
View File

@@ -0,0 +1,10 @@
FROM node:20-alpine
WORKDIR /app
RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 appuser
COPY package.json package-lock.json* ./
RUN npm ci --omit=dev
COPY --chown=appuser:nodejs . .
USER appuser
EXPOSE 3000
ENV NODE_ENV=production
CMD ["node", "server.js"]

View File

@@ -3,18 +3,31 @@ const cors = require('cors');
const helmet = require('helmet'); const helmet = require('helmet');
const compression = require('compression'); const compression = require('compression');
const morgan = require('morgan'); const morgan = require('morgan');
const rateLimit = require('express-rate-limit');
const app = express(); const app = express();
const PORT = process.env.PORT || 3000; const PORT = process.env.PORT || 3000;
// Middleware // Middleware
app.use(helmet()); app.use(helmet());
app.use(cors()); app.use(cors({
origin: process.env.CORS_ORIGIN || 'http://localhost:3000',
credentials: true,
}));
app.use(compression()); app.use(compression());
app.use(morgan('combined')); app.use(morgan('combined'));
app.use(express.json()); app.use(express.json());
app.use(express.urlencoded({ extended: true })); app.use(express.urlencoded({ extended: true }));
const limiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
standardHeaders: true,
legacyHeaders: false,
message: { success: false, error: 'Too many requests, please try again later.' },
});
app.use('/api/', limiter);
// In-memory databases // In-memory databases
const jobs = [ const jobs = [
{ {
@@ -75,7 +88,7 @@ const entrepreneurs = [
const applications = []; const applications = [];
// Health check // Health check
app.get('/health', (req, res) => { const healthHandler = (req, res) => {
res.json({ res.json({
status: 'healthy', status: 'healthy',
service: 'RoadWork API', service: 'RoadWork API',
@@ -87,7 +100,9 @@ app.get('/health', (req, res) => {
total_applications: applications.length total_applications: applications.length
} }
}); });
}); };
app.get('/health', healthHandler);
app.get('/api/health', healthHandler);
// Root // Root
app.get('/', (req, res) => { app.get('/', (req, res) => {

4
roadworld/.dockerignore Normal file
View File

@@ -0,0 +1,4 @@
.git
.gitignore
README.md
.DS_Store

2
roadworld/.env.example Normal file
View File

@@ -0,0 +1,2 @@
# Server
PORT=8080

15
roadworld/Dockerfile Normal file
View File

@@ -0,0 +1,15 @@
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o roadworld .
FROM alpine:3.19
RUN apk --no-cache add ca-certificates
WORKDIR /app
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
COPY --from=builder /app/roadworld .
USER appuser
EXPOSE 8080
CMD ["./roadworld"]

View File

@@ -6,3 +6,30 @@ require (
github.com/gin-gonic/gin v1.9.1 github.com/gin-gonic/gin v1.9.1
github.com/gorilla/websocket v1.5.1 github.com/gorilla/websocket v1.5.1
) )
require (
github.com/bytedance/sonic v1.9.1 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gin-contrib/sse v0.1.0 // 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/goccy/go-json v0.10.2 // 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/mattn/go-isatty v0.0.19 // 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/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

88
roadworld/go.sum Normal file
View File

@@ -0,0 +1,88 @@
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@@ -106,6 +106,7 @@ func main() {
api := r.Group("/api") api := r.Group("/api")
{ {
api.GET("/health", healthCheck)
api.GET("/worlds", getWorlds) api.GET("/worlds", getWorlds)
api.GET("/worlds/:id", getWorld) api.GET("/worlds/:id", getWorld)
api.POST("/worlds", createWorld) api.POST("/worlds", createWorld)