diff --git a/.env.sample b/.env.sample new file mode 100644 index 00000000..73cfac2a --- /dev/null +++ b/.env.sample @@ -0,0 +1,6 @@ +# Sample .env file - fill in the values from Supabase +DB_HOST="" +DB_USER="" +DB_PASSWORD="" +DB_PORT="" +DB_NAME="postgres" \ No newline at end of file diff --git a/.github/workflows/backend-lint.yaml b/.github/workflows/backend-lint.yaml index 2a4188b2..9b0ff912 100644 --- a/.github/workflows/backend-lint.yaml +++ b/.github/workflows/backend-lint.yaml @@ -21,9 +21,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 with: go-version: "1.22" + - name: golangci-lint uses: golangci/golangci-lint-action@v6 with: diff --git a/backend/.gitignore b/backend/.gitignore index db55223b..8a177519 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -12,6 +12,9 @@ server # Test binary, built with `go test -c` *.test +# Autogenerated files +# /database/sqlc + # Output of the go coverage tool, specifically when used with LiteIDE *.out diff --git a/backend/cmd/main.go b/backend/cmd/main.go index da7eab33..742da13e 100644 --- a/backend/cmd/main.go +++ b/backend/cmd/main.go @@ -1,19 +1,53 @@ package main import ( + "context" + "database/sql" + "fmt" "log" + "os" + sqlc "platnm/database/sqlc" + "platnm/routes" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/logger" + "github.com/joho/godotenv" ) func main() { + err := godotenv.Load() + if err != nil { + log.Fatal("Error loading .env file") + } + app := fiber.New() // Middleware app.Use(logger.New()) + host := os.Getenv("DB_HOST") + user := os.Getenv("DB_USER") + password := os.Getenv("DB_PASSWORD") + port := os.Getenv("DB_PORT") + name := os.Getenv("DB_NAME") + + connStr := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=require", host, user, password, name, port) + db, err := sql.Open("postgres", connStr) + if err != nil { + log.Fatal("Failed to initialize the database: ", err) + } + + queries := sqlc.New(db) + ctx := context.Background() + + // list all authors + testData, err := queries.GetTestData(ctx) + if err != nil { + fmt.Println(err) + } + log.Println(testData) + // Routes routes.HelloRoutes(app) diff --git a/backend/database/migrations/schema.sql b/backend/database/migrations/schema.sql new file mode 100644 index 00000000..3a1781d9 --- /dev/null +++ b/backend/database/migrations/schema.sql @@ -0,0 +1,10 @@ +CREATE TABLE albums ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text +); + +CREATE TABLE test ( + id number PRIMARY KEY, + created_at timestamp +); \ No newline at end of file diff --git a/backend/database/queries/queries.sql b/backend/database/queries/queries.sql new file mode 100644 index 00000000..71e66096 --- /dev/null +++ b/backend/database/queries/queries.sql @@ -0,0 +1,5 @@ +-- name: GetAlbums :many +select * from albums; + +-- name: GetTestData :many +select * from test; \ No newline at end of file diff --git a/backend/database/sqlc/db.go b/backend/database/sqlc/db.go new file mode 100644 index 00000000..dacb52ec --- /dev/null +++ b/backend/database/sqlc/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.27.0 + +package database + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...interface{}) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...interface{}) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/backend/database/sqlc/models.go b/backend/database/sqlc/models.go new file mode 100644 index 00000000..8663a439 --- /dev/null +++ b/backend/database/sqlc/models.go @@ -0,0 +1,20 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.27.0 + +package database + +import ( + "database/sql" +) + +type Album struct { + ID int64 + Name string + Bio sql.NullString +} + +type Test struct { + ID interface{} + CreatedAt sql.NullTime +} diff --git a/backend/database/sqlc/queries.sql.go b/backend/database/sqlc/queries.sql.go new file mode 100644 index 00000000..a21b7c7f --- /dev/null +++ b/backend/database/sqlc/queries.sql.go @@ -0,0 +1,64 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.27.0 +// source: queries.sql + +package database + +import ( + "context" +) + +const getAlbums = `-- name: GetAlbums :many +select id, name, bio from albums +` + +func (q *Queries) GetAlbums(ctx context.Context) ([]Album, error) { + rows, err := q.db.QueryContext(ctx, getAlbums) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Album + for rows.Next() { + var i Album + if err := rows.Scan(&i.ID, &i.Name, &i.Bio); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getTestData = `-- name: GetTestData :many +select id, created_at from test +` + +func (q *Queries) GetTestData(ctx context.Context) ([]Test, error) { + rows, err := q.db.QueryContext(ctx, getTestData) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Test + for rows.Next() { + var i Test + if err := rows.Scan(&i.ID, &i.CreatedAt); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/backend/go.mod b/backend/go.mod index e98a6bd3..4767dbab 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -2,7 +2,11 @@ module platnm go 1.22.6 -require github.com/gofiber/fiber/v2 v2.52.5 +require ( + github.com/gofiber/fiber/v2 v2.52.5 + github.com/joho/godotenv v1.5.1 + github.com/lib/pq v1.10.9 +) require ( github.com/andybalholm/brotli v1.0.5 // indirect @@ -15,5 +19,5 @@ require ( github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.51.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/sys v0.17.0 // indirect ) diff --git a/backend/go.sum b/backend/go.sum index fab69789..83376a1a 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -4,8 +4,12 @@ github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yG github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -23,5 +27,5 @@ github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVS github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/backend/sqlc.yaml b/backend/sqlc.yaml new file mode 100644 index 00000000..09ff9824 --- /dev/null +++ b/backend/sqlc.yaml @@ -0,0 +1,10 @@ +version: "2" +sql: + - engine: "postgresql" + queries: "/database/queries" + schema: "/database/migrations" + gen: + go: + package: "database" + out: "/database/sqlc" + sql_package: "database/sql" diff --git a/backend/taskfile.yaml b/backend/taskfile.yaml index dccb2b48..64af361a 100644 --- a/backend/taskfile.yaml +++ b/backend/taskfile.yaml @@ -12,7 +12,13 @@ tasks: summary: Watch for changes to the backend server and rebuild. (Make sure watchexec is installed) cmds: - watchexec -r -e go -- task run + generate: + summary: Generates auto-gen code (sqlc) + cmds: + - sqlc generate build: + deps: + - generate summary: Build backend executables sources: - ./**/*.go @@ -30,6 +36,8 @@ tasks: cmds: - go test ./... lint: + deps: + - generate summary: Run lint checks cmds: - golangci-lint run ./...