Skip to content
Open
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
49 changes: 2 additions & 47 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,52 +39,7 @@ jobs:
run: apk add --update-cache git
- name: Init Database
run: go run test/cmd/initdb/main.go
- name: Go mod tidy
run: go mod tidy
- name: Run tests
run: go test -v ./pkg/...
run-examples:
runs-on: ubuntu-latest
container:
image: golang:1.22-alpine3.20
defaults:
run:
shell: sh
env:
ENV: test
DATABASE_URL: postgres://gooo:password@db:5432/gooo_test?sslmode=disable
services:
db:
image: postgres:16.2
env:
POSTGRES_USER: gooo
POSTGRES_PASSWORD: password
POSTGRES_DB: gooo_test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: Install dependencies
run: apk add --update-cache git
- name: Init Database
run: go run test/cmd/initdb/main.go
# - name: Run API
# run: go run examples/starter/cmd/api/main.go
- name: Run Seed
run: go run examples/starter/cmd/seed/main.go
- name: Run Migration Up
env:
MIGRATION_PATH: examples/starter/db/migrations/*.sql
run: go run examples/starter/cmd/migration/main.go up
- name: Run Migration Down
env:
MIGRATION_PATH: examples/starter/db/migrations/*.sql
run: go run examples/starter/cmd/migration/main.go down
- name: Run Migration Generate
run: go run examples/starter/cmd/migration/main.go generate test
- name: Run Test
run: go test ./examples/starter/...
12 changes: 12 additions & 0 deletions examples/bare/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

Examples of gooo api.


## How to run

## Generate code from swagger.yml

```bash
go run cmd/app.go
```

111 changes: 111 additions & 0 deletions examples/bare/cmd/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package main

import (
"context"
"log"
"net/http"
"time"

"github.com/gooolib/logger"
"github.com/version-1/gooo/examples/bare/internal/swagger"
"github.com/version-1/gooo/pkg/core/api/app"
"github.com/version-1/gooo/pkg/core/api/request"
"github.com/version-1/gooo/pkg/core/api/response"
"github.com/version-1/gooo/pkg/core/api/route"
"github.com/version-1/gooo/pkg/toolkit/middleware"
)

type User struct {
ID string `json:"id"`
Username string `json:"name"`
Email string `json:"email"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
}

type UserCreate struct {
Username string `json:"name"`
Email string `json:"email"`
}

func main() {
cfg := &app.Config{}
cfg.SetLogger(logger.DefaultLogger)

server := &app.App{
Addr: ":8080",
Config: cfg,
ErrorHandler: func(w http.ResponseWriter, r *http.Request, err error) {
cfg.Logger().Errorf("Error: %+v", err)
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("Internal server error"))
},
}

users := route.GroupHandler{
Path: "/users",
Handlers: []route.HandlerInterface{
route.JSON[request.Void, map[string]string]().Get("", func(res *response.Response[map[string]string], req *request.Request[request.Void]) {
res.Render(map[string]string{"message": "ok"})
}),
route.JSON[UserCreate, User]().Post("", func(res *response.Response[User], req *request.Request[UserCreate]) {
body, err := req.Body()
if err != nil {
res.BadRequest(err)
return
}

now := time.Now()
user := User{
ID: "1",
Username: body.Username,
Email: body.Email,
Created: now,
Updated: now,
}
res.Render(user)
}),
route.JSON[request.Void, any]().Get(":id", func(res *response.Response[any], req *request.Request[request.Void]) {
res.Render(map[string]string{"message": "ok"})
}),
route.JSON[request.Void, any]().Patch(":id", func(res *response.Response[any], req *request.Request[request.Void]) {
res.Render(map[string]string{"message": "ok"})
}),
route.JSON[request.Void, any]().Delete(":id", func(res *response.Response[any], req *request.Request[request.Void]) {
res.Render(map[string]string{"message": "ok"})
}),
},
}
swagger := route.GroupHandler{
Path: "/swagger",
Handlers: []route.HandlerInterface{
route.HTML[request.Void]().Get("", func(res *response.Response[[]byte], req *request.Request[request.Void]) {
res.Render(swagger.Index())
}),
route.Text[request.Void]().Get("swagger.yml", func(res *response.Response[[]byte], req *request.Request[request.Void]) {
b, err := swagger.SwaggerYAML()
if err != nil {
res.InternalServerError(err)
return
}

res.Render(b)
}),
},
}

apiv1 := route.GroupHandler{
Path: "/api/v1",
}
apiv1.Add(users.Children()...)
apiv1.Add(swagger.Children()...)
app.WithDefaultMiddlewares(server, apiv1.Children()...)
route.Walk(apiv1.Children(), func(h middleware.Handler) {
server.Logger().Infof("%s", h.String())
})

ctx := context.Background()
if err := server.Run(ctx); err != nil {
log.Fatalf("failed to run app: %s", err)
}
}
48 changes: 48 additions & 0 deletions examples/bare/internal/swagger/swagger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package swagger

import (
"embed"
"fmt"
"io/fs"
)

const hostURL = "http://localhost:8080"

func Index() []byte {
return []byte(fmt.Sprintf(`<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Swagger</title>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/swagger-ui.css" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="SwaggerUI" />
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://unpkg.com/[email protected]/swagger-ui-bundle.js"></script>
<script>
window.onload = () => {
window.ui = SwaggerUIBundle({
url: '%s/api/v1/swagger/swagger.yml',
dom_id: '#swagger-ui',
});
};
</script>
</body>
</html>
`, hostURL))

}

//go:embed *.yml
var swaggerConf embed.FS

func SwaggerYAML() ([]byte, error) {
f, err := fs.ReadFile(swaggerConf, "swagger.yml")
if err != nil {
return f, err
}

return f, nil
}
Loading