init
This commit is contained in:
58
template/services/api/.air.toml
Normal file
58
template/services/api/.air.toml
Normal file
@@ -0,0 +1,58 @@
|
||||
#:schema https://json.schemastore.org/any.json
|
||||
|
||||
env_files = []
|
||||
root = "."
|
||||
testdata_dir = "testdata"
|
||||
tmp_dir = "tmp"
|
||||
|
||||
[build]
|
||||
args_bin = []
|
||||
bin = "./tmp/main"
|
||||
cmd = "go build -o ./tmp/main ."
|
||||
delay = 1000
|
||||
entrypoint = ["./tmp/main","serve"]
|
||||
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
|
||||
exclude_file = []
|
||||
exclude_regex = ["_test.go"]
|
||||
exclude_unchanged = false
|
||||
follow_symlink = false
|
||||
full_bin = ""
|
||||
ignore_dangerous_root_dir = false
|
||||
include_dir = []
|
||||
include_ext = ["go", "tpl", "tmpl", "html"]
|
||||
include_file = []
|
||||
kill_delay = "0s"
|
||||
log = "build-errors.log"
|
||||
poll = false
|
||||
poll_interval = 0
|
||||
post_cmd = []
|
||||
pre_cmd = []
|
||||
rerun = false
|
||||
rerun_delay = 500
|
||||
send_interrupt = false
|
||||
stop_on_error = false
|
||||
|
||||
[color]
|
||||
app = ""
|
||||
build = "yellow"
|
||||
main = "magenta"
|
||||
runner = "green"
|
||||
watcher = "cyan"
|
||||
|
||||
[log]
|
||||
main_only = false
|
||||
silent = false
|
||||
time = false
|
||||
|
||||
[misc]
|
||||
clean_on_exit = false
|
||||
|
||||
[proxy]
|
||||
app_port = 0
|
||||
app_start_timeout = 0
|
||||
enabled = false
|
||||
proxy_port = 0
|
||||
|
||||
[screen]
|
||||
clear_on_rebuild = false
|
||||
keep_scroll = true
|
||||
1
template/services/api/.gitignore
vendored
Normal file
1
template/services/api/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
tmp
|
||||
0
template/services/api/LICENSE
Normal file
0
template/services/api/LICENSE
Normal file
45
template/services/api/cmd/configInit.go
Normal file
45
template/services/api/cmd/configInit.go
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright © 2026 NAME HERE <EMAIL ADDRESS>
|
||||
*/
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"<@var(context.project.goprefix)>/<@var(context.project.name)>/config"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// configInitCmd represents the configInit command
|
||||
var configInitCmd = &cobra.Command{
|
||||
Use: "configInit",
|
||||
Short: "A brief description of your command",
|
||||
Long: `A longer description that spans multiple lines and likely contains examples
|
||||
and usage of using your command. For example:
|
||||
|
||||
Cobra is a CLI library for Go that empowers applications.
|
||||
This application is a tool to generate the needed files
|
||||
to quickly create a Cobra application.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := config.Write(*config.DefaultConf)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(configInitCmd)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
|
||||
// Cobra supports Persistent Flags which will work for this command
|
||||
// and all subcommands, e.g.:
|
||||
// configInitCmd.PersistentFlags().String("foo", "", "A help for foo")
|
||||
|
||||
// Cobra supports local flags which will only run when this command
|
||||
// is called directly, e.g.:
|
||||
// configInitCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
||||
37
template/services/api/cmd/migrate.go
Normal file
37
template/services/api/cmd/migrate.go
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright © 2026 NAME HERE <EMAIL ADDRESS>
|
||||
*/
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"<@var(context.project.goprefix)>/<@var(context.project.name)>/db"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// migrateCmd represents the migrate command
|
||||
var migrateCmd = &cobra.Command{
|
||||
Use: "migrate",
|
||||
Short: "run database migrations",
|
||||
Long: ``,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
err := db.RunDbMigrations()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(migrateCmd)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
|
||||
// Cobra supports Persistent Flags which will work for this command
|
||||
// and all subcommands, e.g.:
|
||||
// migrateCmd.PersistentFlags().String("foo", "", "A help for foo")
|
||||
|
||||
// Cobra supports local flags which will only run when this command
|
||||
// is called directly, e.g.:
|
||||
// migrateCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
||||
45
template/services/api/cmd/root.go
Normal file
45
template/services/api/cmd/root.go
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright © 2026 NAME HERE <EMAIL ADDRESS>
|
||||
*/
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "<@var(context.project.name)>",
|
||||
Short: "A brief description of your application",
|
||||
Long: `A longer description that spans multiple lines and likely contains
|
||||
examples and usage of using your application. For example:
|
||||
|
||||
Cobra is a CLI library for Go that empowers applications.
|
||||
This application is a tool to generate the needed files
|
||||
to quickly create a Cobra application.`,
|
||||
// Uncomment the following line if your bare application
|
||||
// has an action associated with it:
|
||||
// Run: func(cmd *cobra.Command, args []string) { },
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
|
||||
// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.<@var(context.project.name)>.yaml)")
|
||||
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
||||
81
template/services/api/cmd/serve.go
Normal file
81
template/services/api/cmd/serve.go
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
Copyright © 2026 NAME HERE <EMAIL ADDRESS>
|
||||
*/
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"<@var(context.project.goprefix)>/<@var(context.project.name)>/config"
|
||||
"<@var(context.project.goprefix)>/<@var(context.project.name)>/db"
|
||||
"<@var(context.project.goprefix)>/<@var(context.project.name)>/server/todo"
|
||||
connectors "connectrpc.com/cors"
|
||||
"context"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
"github.com/rs/cors"
|
||||
"github.com/spf13/cobra"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// serveCmd represents the serve command
|
||||
var serveCmd = &cobra.Command{
|
||||
Use: "serve",
|
||||
Short: "start server",
|
||||
Long: ``,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
err := config.Load()
|
||||
if err != nil {
|
||||
err := config.Write(*config.DefaultConf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
conf := *config.Conf
|
||||
ctx := context.Background()
|
||||
db_url := "postgres://" + conf.Database.User + ":" + conf.Database.Password + "@" + conf.Database.Host + ":" + strconv.Itoa(conf.Database.Port) + "/" + conf.Database.Name
|
||||
db_url = db_url + "?sslmode=disable"
|
||||
conn, err := pgxpool.New(ctx, db_url)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
err = db.RunDbMigrations()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
db.Q = db.New(conn)
|
||||
middleware := cors.New(cors.Options{
|
||||
AllowedOrigins: conf.Server.FrontendUrls,
|
||||
AllowedMethods: connectors.AllowedMethods(),
|
||||
AllowedHeaders: connectors.AllowedHeaders(),
|
||||
ExposedHeaders: connectors.ExposedHeaders(),
|
||||
Debug: true,
|
||||
})
|
||||
mux := http.NewServeMux()
|
||||
todoPath, todoHandler := todo.GetPathHandler()
|
||||
mux.Handle(todoPath, todoHandler)
|
||||
p := new(http.Protocols)
|
||||
p.SetHTTP1(true)
|
||||
p.SetUnencryptedHTTP2(true)
|
||||
s := http.Server{
|
||||
Addr: strings.Join([]string{conf.Server.Host, strconv.Itoa(conf.Server.Port)}, ":"),
|
||||
Handler: middleware.Handler(mux),
|
||||
Protocols: p,
|
||||
}
|
||||
s.ListenAndServe()
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(serveCmd)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
|
||||
// Cobra supports Persistent Flags which will work for this command
|
||||
// and all subcommands, e.g.:
|
||||
// serveCmd.PersistentFlags().String("foo", "", "A help for foo")
|
||||
|
||||
// Cobra supports local flags which will only run when this command
|
||||
// is called directly, e.g.:
|
||||
// serveCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
||||
81
template/services/api/config/config.go
Normal file
81
template/services/api/config/config.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"github.com/adrg/xdg"
|
||||
"github.com/pelletier/go-toml"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var confPath string
|
||||
var Conf *Config
|
||||
var DefaultConf *Config
|
||||
|
||||
func init() {
|
||||
confPath = filepath.Join(xdg.ConfigHome, "<@var(context.project.name)>", "config.toml")
|
||||
Conf = &Config{}
|
||||
DefaultConf = &Config{
|
||||
Server: Server{
|
||||
Host: "127.0.0.1",
|
||||
Port: 8080,
|
||||
FrontendUrls: []string{"http://localhost:5173"},
|
||||
},
|
||||
Database: Database{
|
||||
User: "pp",
|
||||
Password: "<@var(context.project.name)>",
|
||||
Host: "127.0.0.1",
|
||||
Port: 5432,
|
||||
Name: "<@var(context.project.name)>",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func Load() error {
|
||||
confContent, err := os.ReadFile(confPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return toml.Unmarshal(confContent, Conf)
|
||||
|
||||
}
|
||||
|
||||
func Write(config Config) error {
|
||||
confContent, err := toml.Marshal(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dir := filepath.Dir(confPath)
|
||||
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.WriteFile(confPath, confContent, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := Load(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
Host string
|
||||
Port int
|
||||
FrontendUrls []string
|
||||
}
|
||||
|
||||
type Database struct {
|
||||
User string
|
||||
Password string
|
||||
Host string
|
||||
Port int
|
||||
Name string
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Server Server
|
||||
Database Database
|
||||
}
|
||||
32
template/services/api/db/db.go
Normal file
32
template/services/api/db/db.go
Normal file
@@ -0,0 +1,32 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
)
|
||||
|
||||
type DBTX interface {
|
||||
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
|
||||
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
|
||||
QueryRow(context.Context, string, ...interface{}) pgx.Row
|
||||
}
|
||||
|
||||
func New(db DBTX) *Queries {
|
||||
return &Queries{db: db}
|
||||
}
|
||||
|
||||
type Queries struct {
|
||||
db DBTX
|
||||
}
|
||||
|
||||
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
|
||||
return &Queries{
|
||||
db: tx,
|
||||
}
|
||||
}
|
||||
6
template/services/api/db/dbfs.go
Normal file
6
template/services/api/db/dbfs.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package db
|
||||
|
||||
import "embed"
|
||||
|
||||
//go:embed migrations/*.sql
|
||||
var MigrationsFs embed.FS
|
||||
60
template/services/api/db/lib.go
Normal file
60
template/services/api/db/lib.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"<@var(context.project.goprefix)>/<@var(context.project.name)>/config"
|
||||
"github.com/amacneil/dbmate/v2/pkg/dbmate"
|
||||
_ "github.com/amacneil/dbmate/v2/pkg/driver/postgres"
|
||||
"log"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var Q *Queries
|
||||
|
||||
func RunDbMigrations() error {
|
||||
|
||||
err := config.Load()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conf := *config.Conf
|
||||
dbUrl, err := url.Parse(strings.Join([]string{
|
||||
"postgresql://",
|
||||
conf.Database.User,
|
||||
":",
|
||||
conf.Database.Password,
|
||||
"@",
|
||||
conf.Database.Host,
|
||||
":",
|
||||
strconv.Itoa(conf.Database.Port),
|
||||
"/",
|
||||
conf.Database.Name,
|
||||
}, ""))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
db := dbmate.New(dbUrl)
|
||||
db.FS = MigrationsFs
|
||||
db.MigrationsDir = []string{"migrations"}
|
||||
migrations, err := db.FindMigrations()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, m := range migrations {
|
||||
log.Default().Println(m.Version, m.FilePath)
|
||||
}
|
||||
db.AutoDumpSchema = false
|
||||
log.Default().Println("\nApplying...")
|
||||
err = db.CreateAndMigrate()
|
||||
if err != nil {
|
||||
log.Default().Println(err.Error())
|
||||
}
|
||||
err = db.DumpSchema()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
10
template/services/api/db/migrations/20260404121052_init.sql
Normal file
10
template/services/api/db/migrations/20260404121052_init.sql
Normal file
@@ -0,0 +1,10 @@
|
||||
-- migrate:up
|
||||
CREATE TABLE todo (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
task VARCHAR(255) NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
done bool DEFAULT false
|
||||
);
|
||||
-- migrate:down
|
||||
DROP TABLE todo;
|
||||
17
template/services/api/db/models.go
Normal file
17
template/services/api/db/models.go
Normal file
@@ -0,0 +1,17 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
type Todo struct {
|
||||
ID pgtype.UUID
|
||||
Task string
|
||||
CreatedAt pgtype.Timestamp
|
||||
UpdatedAt pgtype.Timestamp
|
||||
Done pgtype.Bool
|
||||
}
|
||||
14
template/services/api/db/query/todo.sql
Normal file
14
template/services/api/db/query/todo.sql
Normal file
@@ -0,0 +1,14 @@
|
||||
-- name: CreateTodo :one
|
||||
insert into todo (id,task) values ($1,$2) returning *;
|
||||
|
||||
-- name: ListTodos :many
|
||||
select * from todo;
|
||||
|
||||
-- name: GetTodo :one
|
||||
select * from todo where id = $1 limit 1;
|
||||
|
||||
-- name: UpdateTodo :one
|
||||
update todo set task = $1, done = $2 where id = $3 returning *;
|
||||
|
||||
-- name: DeleteTodo :exec
|
||||
delete from todo where id = $1;
|
||||
86
template/services/api/db/schema.sql
Normal file
86
template/services/api/db/schema.sql
Normal file
@@ -0,0 +1,86 @@
|
||||
\restrict dbmate
|
||||
|
||||
-- Dumped from database version 17.9
|
||||
-- Dumped by pg_dump version 17.9
|
||||
|
||||
SET statement_timeout = 0;
|
||||
SET lock_timeout = 0;
|
||||
SET idle_in_transaction_session_timeout = 0;
|
||||
SET transaction_timeout = 0;
|
||||
SET client_encoding = 'UTF8';
|
||||
SET standard_conforming_strings = on;
|
||||
SELECT pg_catalog.set_config('search_path', '', false);
|
||||
SET check_function_bodies = false;
|
||||
SET xmloption = content;
|
||||
SET client_min_messages = warning;
|
||||
SET row_security = off;
|
||||
|
||||
--
|
||||
-- Name: pgcrypto; Type: EXTENSION; Schema: -; Owner: -
|
||||
--
|
||||
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA public;
|
||||
|
||||
|
||||
--
|
||||
-- Name: EXTENSION pgcrypto; Type: COMMENT; Schema: -; Owner: -
|
||||
--
|
||||
|
||||
COMMENT ON EXTENSION pgcrypto IS 'cryptographic functions';
|
||||
|
||||
|
||||
SET default_tablespace = '';
|
||||
|
||||
SET default_table_access_method = heap;
|
||||
|
||||
--
|
||||
-- Name: schema_migrations; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.schema_migrations (
|
||||
version character varying NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: todo; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.todo (
|
||||
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
||||
task character varying(255) NOT NULL,
|
||||
created_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
|
||||
done boolean DEFAULT false
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.schema_migrations
|
||||
ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version);
|
||||
|
||||
|
||||
--
|
||||
-- Name: todo todo_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.todo
|
||||
ADD CONSTRAINT todo_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- PostgreSQL database dump complete
|
||||
--
|
||||
|
||||
\unrestrict dbmate
|
||||
|
||||
|
||||
--
|
||||
-- Dbmate schema migrations
|
||||
--
|
||||
|
||||
INSERT INTO public.schema_migrations (version) VALUES
|
||||
('20260404121052');
|
||||
113
template/services/api/db/todo.sql.go
Normal file
113
template/services/api/db/todo.sql.go
Normal file
@@ -0,0 +1,113 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: todo.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const createTodo = `-- name: CreateTodo :one
|
||||
insert into todo (id,task) values ($1,$2) returning id, task, created_at, updated_at, done
|
||||
`
|
||||
|
||||
type CreateTodoParams struct {
|
||||
ID pgtype.UUID
|
||||
Task string
|
||||
}
|
||||
|
||||
func (q *Queries) CreateTodo(ctx context.Context, arg CreateTodoParams) (Todo, error) {
|
||||
row := q.db.QueryRow(ctx, createTodo, arg.ID, arg.Task)
|
||||
var i Todo
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Task,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Done,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteTodo = `-- name: DeleteTodo :exec
|
||||
delete from todo where id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteTodo(ctx context.Context, id pgtype.UUID) error {
|
||||
_, err := q.db.Exec(ctx, deleteTodo, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const getTodo = `-- name: GetTodo :one
|
||||
select id, task, created_at, updated_at, done from todo where id = $1 limit 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetTodo(ctx context.Context, id pgtype.UUID) (Todo, error) {
|
||||
row := q.db.QueryRow(ctx, getTodo, id)
|
||||
var i Todo
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Task,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Done,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listTodos = `-- name: ListTodos :many
|
||||
select id, task, created_at, updated_at, done from todo
|
||||
`
|
||||
|
||||
func (q *Queries) ListTodos(ctx context.Context) ([]Todo, error) {
|
||||
rows, err := q.db.Query(ctx, listTodos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Todo
|
||||
for rows.Next() {
|
||||
var i Todo
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Task,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Done,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateTodo = `-- name: UpdateTodo :one
|
||||
update todo set task = $1, done = $2 where id = $3 returning id, task, created_at, updated_at, done
|
||||
`
|
||||
|
||||
type UpdateTodoParams struct {
|
||||
Task string
|
||||
Done pgtype.Bool
|
||||
ID pgtype.UUID
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateTodo(ctx context.Context, arg UpdateTodoParams) (Todo, error) {
|
||||
row := q.db.QueryRow(ctx, updateTodo, arg.Task, arg.Done, arg.ID)
|
||||
var i Todo
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Task,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Done,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
34
template/services/api/go.mod
Normal file
34
template/services/api/go.mod
Normal file
@@ -0,0 +1,34 @@
|
||||
module <@var(context.project.goprefix)>/<@var(context.project.name)>
|
||||
|
||||
go 1.25.7
|
||||
|
||||
require (
|
||||
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.9-20250912141014-52f32327d4b0.1 // indirect
|
||||
buf.build/go/protovalidate v1.0.0 // indirect
|
||||
cel.dev/expr v0.24.0 // indirect
|
||||
connectrpc.com/connect v1.19.1 // indirect
|
||||
connectrpc.com/cors v0.1.0 // indirect
|
||||
connectrpc.com/validate v0.6.0 // indirect
|
||||
github.com/adrg/xdg v0.5.3 // indirect
|
||||
github.com/amacneil/dbmate/v2 v2.32.0 // indirect
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
|
||||
github.com/google/cel-go v0.26.1 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/pgx/v5 v5.9.1 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/lib/pq v1.12.0 // indirect
|
||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||
github.com/rs/cors v1.11.1 // indirect
|
||||
github.com/spf13/cobra v1.10.2 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/stoewer/go-strcase v1.3.1 // indirect
|
||||
golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
golang.org/x/sys v0.42.0 // indirect
|
||||
golang.org/x/text v0.35.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260319201613-d00831a3d3e7 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260319201613-d00831a3d3e7 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
)
|
||||
79
template/services/api/go.sum
Normal file
79
template/services/api/go.sum
Normal file
@@ -0,0 +1,79 @@
|
||||
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.9-20250912141014-52f32327d4b0.1 h1:DQLS/rRxLHuugVzjJU5AvOwD57pdFl9he/0O7e5P294=
|
||||
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.9-20250912141014-52f32327d4b0.1/go.mod h1:aY3zbkNan5F+cGm9lITDP6oxJIwu0dn9KjJuJjWaHkg=
|
||||
buf.build/go/protovalidate v1.0.0 h1:IAG1etULddAy93fiBsFVhpj7es5zL53AfB/79CVGtyY=
|
||||
buf.build/go/protovalidate v1.0.0/go.mod h1:KQmEUrcQuC99hAw+juzOEAmILScQiKBP1Oc36vvCLW8=
|
||||
cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=
|
||||
cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
|
||||
connectrpc.com/connect v1.19.1 h1:R5M57z05+90EfEvCY1b7hBxDVOUl45PrtXtAV2fOC14=
|
||||
connectrpc.com/connect v1.19.1/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w=
|
||||
connectrpc.com/cors v0.1.0 h1:f3gTXJyDZPrDIZCQ567jxfD9PAIpopHiRDnJRt3QuOQ=
|
||||
connectrpc.com/cors v0.1.0/go.mod h1:v8SJZCPfHtGH1zsm+Ttajpozd4cYIUryl4dFB6QEpfg=
|
||||
connectrpc.com/validate v0.6.0 h1:DcrgDKt2ZScrUs/d/mh9itD2yeEa0UbBBa+i0mwzx+4=
|
||||
connectrpc.com/validate v0.6.0/go.mod h1:ihrpI+8gVbLH1fvVWJL1I3j0CfWnF8P/90LsmluRiZs=
|
||||
github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78=
|
||||
github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ=
|
||||
github.com/amacneil/dbmate/v2 v2.32.0 h1:DJWt+NRWlphTv1HXWWcAU7gsJKm/Ov8/+8k6yqLz8vA=
|
||||
github.com/amacneil/dbmate/v2 v2.32.0/go.mod h1:Kwax92bT+ZgqIXll9M+0QGuHVuu7O7AhsE+5p6PTqDc=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/google/cel-go v0.26.1 h1:iPbVVEdkhTX++hpe3lzSk7D3G3QSYqLGoHOcEio+UXQ=
|
||||
github.com/google/cel-go v0.26.1/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.9.1 h1:uwrxJXBnx76nyISkhr33kQLlUqjv7et7b9FjCen/tdc=
|
||||
github.com/jackc/pgx/v5 v5.9.1/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4=
|
||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/lib/pq v1.12.0 h1:mC1zeiNamwKBecjHarAr26c/+d8V5w/u4J0I/yASbJo=
|
||||
github.com/lib/pq v1.12.0/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA=
|
||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
|
||||
github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
|
||||
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
|
||||
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stoewer/go-strcase v1.3.1 h1:iS0MdW+kVTxgMoE1LAZyMiYJFKlOzLooE4MxjirtkAs=
|
||||
github.com/stoewer/go-strcase v1.3.1/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
|
||||
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=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 h1:jiDhWWeC7jfWqR9c/uplMOqJ0sbNlNWv0UkzE0vX1MA=
|
||||
golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90/go.mod h1:xE1HEv6b+1SCZ5/uscMRjUBKtIxworgEcEi+/n9NQDQ=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
|
||||
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
|
||||
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 h1:XzmzkmB14QhVhgnawEVsOn6OFsnpyxNPRY9QV01dNB0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260319201613-d00831a3d3e7 h1:41r6JMbpzBMen0R/4TZeeAmGXSJC7DftGINUodzTkPI=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260319201613-d00831a3d3e7/go.mod h1:EIQZ5bFCfRQDV4MhRle7+OgjNtZ6P1PiZBgAKuxXu/Y=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260319201613-d00831a3d3e7 h1:ndE4FoJqsIceKP2oYSnUZqhTdYufCYYkqwtFzfrhI7w=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260319201613-d00831a3d3e7/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
||||
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
11
template/services/api/main.go
Normal file
11
template/services/api/main.go
Normal file
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
Copyright © 2026 NAME HERE <EMAIL ADDRESS>
|
||||
|
||||
*/
|
||||
package main
|
||||
|
||||
import "<@var(context.project.goprefix)>/<@var(context.project.name)>/cmd"
|
||||
|
||||
func main() {
|
||||
cmd.Execute()
|
||||
}
|
||||
116
template/services/api/server/todo/todo.go
Normal file
116
template/services/api/server/todo/todo.go
Normal file
@@ -0,0 +1,116 @@
|
||||
package todo
|
||||
|
||||
import (
|
||||
"connectrpc.com/connect"
|
||||
"connectrpc.com/validate"
|
||||
"context"
|
||||
"<@var(context.project.goprefix)>/<@var(context.project.name)>/db"
|
||||
todov1 "<@var(context.project.goprefix)>/<@var(context.project.name)>/gen/todo/v1"
|
||||
"<@var(context.project.goprefix)>/<@var(context.project.name)>/gen/todo/v1/todov1connect"
|
||||
. "<@var(context.project.goprefix)>/<@var(context.project.name)>/utils"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type TodoServer struct{}
|
||||
|
||||
func (srv *TodoServer) CreateTodo(ctx context.Context, req *connect.Request[todov1.CreateTodoRequest]) (*connect.Response[todov1.CreateTodoResponse], error) {
|
||||
var id pgtype.UUID
|
||||
err := id.Scan(*req.Msg.Todo.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
todo, err := db.Q.CreateTodo(ctx, db.CreateTodoParams{
|
||||
ID: id,
|
||||
Task: req.Msg.Todo.Task,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &connect.Response[todov1.CreateTodoResponse]{
|
||||
Msg: &todov1.CreateTodoResponse{
|
||||
Todo: &todov1.Todo{
|
||||
Id: StrPtr(todo.ID.String()),
|
||||
Task: todo.Task,
|
||||
CreatedAt: StrPtr(todo.CreatedAt.Time.Format(time.RFC3339)),
|
||||
UpdatesAt: StrPtr(todo.UpdatedAt.Time.Format(time.RFC3339)),
|
||||
Done: BoolPtr(todo.Done.Bool),
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (srv *TodoServer) ListTodos(ctx context.Context, req *connect.Request[todov1.ListTodosRequest]) (*connect.Response[todov1.ListTodosResponse], error) {
|
||||
todos, err := db.Q.ListTodos(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reponseTodos := []*todov1.Todo{}
|
||||
for _, todo := range todos {
|
||||
reponseTodos = append(reponseTodos, &todov1.Todo{
|
||||
Id: StrPtr(todo.ID.String()),
|
||||
Task: todo.Task,
|
||||
CreatedAt: StrPtr(todo.CreatedAt.Time.Format(time.RFC3339)),
|
||||
UpdatesAt: StrPtr(todo.UpdatedAt.Time.Format(time.RFC3339)),
|
||||
Done: BoolPtr(todo.Done.Bool),
|
||||
})
|
||||
}
|
||||
|
||||
return &connect.Response[todov1.ListTodosResponse]{
|
||||
Msg: &todov1.ListTodosResponse{
|
||||
Todos: reponseTodos,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (srv *TodoServer) UpdateTodo(ctx context.Context, req *connect.Request[todov1.UpdateTodoRequest]) (*connect.Response[todov1.UpdateTodoResponse], error) {
|
||||
var id pgtype.UUID
|
||||
err := id.Scan(*req.Msg.Todo.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
todo, err := db.Q.UpdateTodo(ctx, db.UpdateTodoParams{
|
||||
Task: req.Msg.Todo.Task,
|
||||
Done: pgtype.Bool{
|
||||
Bool: *req.Msg.Todo.Done,
|
||||
Valid: true,
|
||||
},
|
||||
ID: id,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &connect.Response[todov1.UpdateTodoResponse]{
|
||||
Msg: &todov1.UpdateTodoResponse{
|
||||
Todo: &todov1.Todo{
|
||||
Id: StrPtr(todo.ID.String()),
|
||||
Task: todo.Task,
|
||||
CreatedAt: StrPtr(todo.CreatedAt.Time.Format(time.RFC3339)),
|
||||
UpdatesAt: StrPtr(todo.UpdatedAt.Time.Format(time.RFC3339)),
|
||||
Done: BoolPtr(todo.Done.Bool),
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
func (srv *TodoServer) DeleteTodo(ctx context.Context, req *connect.Request[todov1.DeleteTodoRequest]) (*connect.Response[todov1.DeleteTodoResponse], error) {
|
||||
var id pgtype.UUID
|
||||
err := id.Scan(*req.Msg.Todo.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = db.Q.DeleteTodo(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &connect.Response[todov1.DeleteTodoResponse]{
|
||||
Msg: &todov1.DeleteTodoResponse{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func GetPathHandler() (path string, handler http.Handler) {
|
||||
path, handler = todov1connect.NewTodoServiceHandler(&TodoServer{}, connect.WithInterceptors(validate.NewInterceptor()))
|
||||
return
|
||||
}
|
||||
10
template/services/api/sqlc.yaml
Normal file
10
template/services/api/sqlc.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
version: "2"
|
||||
sql:
|
||||
- engine: "postgresql"
|
||||
queries: "db/query"
|
||||
schema: "db/migrations"
|
||||
gen:
|
||||
go:
|
||||
package: "db"
|
||||
out: "db"
|
||||
sql_package: "pgx/v5"
|
||||
9
template/services/api/utils/utils.go
Normal file
9
template/services/api/utils/utils.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package utils
|
||||
|
||||
func StrPtr(v string) *string {
|
||||
return &v
|
||||
}
|
||||
|
||||
func BoolPtr(v bool) *bool {
|
||||
return &v
|
||||
}
|
||||
Reference in New Issue
Block a user