~repos /gromer
git clone https://pyrossh.dev/repos/gromer.git
gromer is a framework and cli to build multipage web apps in golang using htmx and alpinejs.
fb9440fa
—
Peter John 3 years ago
simplify example
- _example/Dockerfile.dbmate +0 -4
- _example/components/todo.go +2 -2
- _example/config/config.go +0 -11
- _example/db/db.go +0 -29
- _example/db/init.go +0 -18
- _example/db/migrations/20211128110219_create_todos_table.sql +0 -11
- _example/db/models.go +0 -15
- _example/db/queries/todo.sql +0 -26
- _example/db/schema.sql +0 -64
- _example/db/sqlc.yaml +0 -11
- _example/db/todo.sql.go +0 -139
- _example/makefile +2 -11
- _example/pages/api/todos/_todoId_/delete.go +2 -2
- _example/pages/api/todos/_todoId_/get.go +3 -8
- _example/pages/api/todos/_todoId_/put.go +6 -7
- _example/pages/api/todos/get.go +5 -10
- _example/pages/api/todos/post.go +3 -3
- _example/pages/get.go +1 -2
- _example/services/todo.go +77 -0
_example/Dockerfile.dbmate
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
FROM amacneil/dbmate
|
|
2
|
-
|
|
3
|
-
WORKDIR /
|
|
4
|
-
COPY ./db ./db
|
_example/components/todo.go
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
package components
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
|
-
"github.com/pyros2097/gromer/_example/
|
|
4
|
+
"github.com/pyros2097/gromer/_example/services"
|
|
5
5
|
. "github.com/pyros2097/gromer/handlebars"
|
|
6
6
|
)
|
|
7
7
|
|
|
8
8
|
type TodoProps struct {
|
|
9
|
-
Todo *
|
|
9
|
+
Todo *services.Todo `json:"todo"`
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
func Todo(props TodoProps) *Template {
|
_example/config/config.go
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
package config
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"os"
|
|
5
|
-
)
|
|
6
|
-
|
|
7
|
-
var DATABASE_URL string
|
|
8
|
-
|
|
9
|
-
func init() {
|
|
10
|
-
DATABASE_URL = os.Getenv("DATABASE_URL")
|
|
11
|
-
}
|
_example/db/db.go
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
// Code generated by sqlc. DO NOT EDIT.
|
|
2
|
-
|
|
3
|
-
package db
|
|
4
|
-
|
|
5
|
-
import (
|
|
6
|
-
"context"
|
|
7
|
-
"database/sql"
|
|
8
|
-
)
|
|
9
|
-
|
|
10
|
-
type DBTX interface {
|
|
11
|
-
ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
|
|
12
|
-
PrepareContext(context.Context, string) (*sql.Stmt, error)
|
|
13
|
-
QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
|
|
14
|
-
QueryRowContext(context.Context, string, ...interface{}) *sql.Row
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
func New(db DBTX) *Queries {
|
|
18
|
-
return &Queries{db: db}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
type Queries struct {
|
|
22
|
-
db DBTX
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
|
|
26
|
-
return &Queries{
|
|
27
|
-
db: tx,
|
|
28
|
-
}
|
|
29
|
-
}
|
_example/db/init.go
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
package db
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"database/sql"
|
|
5
|
-
|
|
6
|
-
_ "github.com/lib/pq"
|
|
7
|
-
"github.com/pyros2097/gromer/_example/config"
|
|
8
|
-
)
|
|
9
|
-
|
|
10
|
-
var Query *Queries
|
|
11
|
-
|
|
12
|
-
func init() {
|
|
13
|
-
sqlDB, err := sql.Open("postgres", config.DATABASE_URL)
|
|
14
|
-
if err != nil {
|
|
15
|
-
panic(err)
|
|
16
|
-
}
|
|
17
|
-
Query = New(sqlDB)
|
|
18
|
-
}
|
_example/db/migrations/20211128110219_create_todos_table.sql
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
-- migrate:up
|
|
2
|
-
CREATE TABLE todos (
|
|
3
|
-
id TEXT NOT NULL PRIMARY KEY,
|
|
4
|
-
text TEXT NOT NULL,
|
|
5
|
-
completed BOOLEAN NOT NULL,
|
|
6
|
-
created_at TIMESTAMP NOT NULL,
|
|
7
|
-
updated_at TIMESTAMP NOT NULL
|
|
8
|
-
);
|
|
9
|
-
|
|
10
|
-
-- migrate:down
|
|
11
|
-
DROP TABLE todos;
|
_example/db/models.go
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// Code generated by sqlc. DO NOT EDIT.
|
|
2
|
-
|
|
3
|
-
package db
|
|
4
|
-
|
|
5
|
-
import (
|
|
6
|
-
"time"
|
|
7
|
-
)
|
|
8
|
-
|
|
9
|
-
type Todo struct {
|
|
10
|
-
ID string `json:"id"`
|
|
11
|
-
Text string `json:"text"`
|
|
12
|
-
Completed bool `json:"completed"`
|
|
13
|
-
CreatedAt time.Time `json:"createdAt"`
|
|
14
|
-
UpdatedAt time.Time `json:"updatedAt"`
|
|
15
|
-
}
|
_example/db/queries/todo.sql
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
-- name: GetTodo :one
|
|
2
|
-
SELECT * FROM todos
|
|
3
|
-
WHERE id = $1 LIMIT 1;
|
|
4
|
-
|
|
5
|
-
-- name: ListTodos :many
|
|
6
|
-
SELECT * FROM todos
|
|
7
|
-
ORDER BY id LIMIT $1 OFFSET $2;
|
|
8
|
-
|
|
9
|
-
-- name: CreateTodo :one
|
|
10
|
-
INSERT INTO todos (
|
|
11
|
-
id, text, completed, created_at, updated_at
|
|
12
|
-
) VALUES (
|
|
13
|
-
$1, $2, $3, $4, $5
|
|
14
|
-
) RETURNING *;
|
|
15
|
-
|
|
16
|
-
-- name: UpdateTodo :one
|
|
17
|
-
UPDATE todos
|
|
18
|
-
SET
|
|
19
|
-
completed = $2,
|
|
20
|
-
updated_at = $3
|
|
21
|
-
WHERE id = $1
|
|
22
|
-
RETURNING *;
|
|
23
|
-
|
|
24
|
-
-- name: DeleteTodo :exec
|
|
25
|
-
DELETE FROM todos
|
|
26
|
-
WHERE id = $1;
|
_example/db/schema.sql
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
SET statement_timeout = 0;
|
|
2
|
-
SET lock_timeout = 0;
|
|
3
|
-
SET idle_in_transaction_session_timeout = 0;
|
|
4
|
-
SET client_encoding = 'UTF8';
|
|
5
|
-
SET standard_conforming_strings = on;
|
|
6
|
-
SELECT pg_catalog.set_config('search_path', '', false);
|
|
7
|
-
SET check_function_bodies = false;
|
|
8
|
-
SET xmloption = content;
|
|
9
|
-
SET client_min_messages = warning;
|
|
10
|
-
SET row_security = off;
|
|
11
|
-
|
|
12
|
-
SET default_tablespace = '';
|
|
13
|
-
|
|
14
|
-
SET default_table_access_method = heap;
|
|
15
|
-
|
|
16
|
-
--
|
|
17
|
-
-- Name: schema_migrations; Type: TABLE; Schema: public; Owner: -
|
|
18
|
-
--
|
|
19
|
-
|
|
20
|
-
CREATE TABLE public.schema_migrations (
|
|
21
|
-
version character varying(255) NOT NULL
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
--
|
|
26
|
-
-- Name: todos; Type: TABLE; Schema: public; Owner: -
|
|
27
|
-
--
|
|
28
|
-
|
|
29
|
-
CREATE TABLE public.todos (
|
|
30
|
-
id text NOT NULL,
|
|
31
|
-
text text NOT NULL,
|
|
32
|
-
completed boolean NOT NULL,
|
|
33
|
-
created_at timestamp without time zone NOT NULL,
|
|
34
|
-
updated_at timestamp without time zone NOT NULL
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
--
|
|
39
|
-
-- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
40
|
-
--
|
|
41
|
-
|
|
42
|
-
ALTER TABLE ONLY public.schema_migrations
|
|
43
|
-
ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
--
|
|
47
|
-
-- Name: todos todos_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
48
|
-
--
|
|
49
|
-
|
|
50
|
-
ALTER TABLE ONLY public.todos
|
|
51
|
-
ADD CONSTRAINT todos_pkey PRIMARY KEY (id);
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
--
|
|
55
|
-
-- PostgreSQL database dump complete
|
|
56
|
-
--
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
--
|
|
60
|
-
-- Dbmate schema migrations
|
|
61
|
-
--
|
|
62
|
-
|
|
63
|
-
INSERT INTO public.schema_migrations (version) VALUES
|
|
64
|
-
('20211128110219');
|
_example/db/sqlc.yaml
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
version: '1'
|
|
2
|
-
packages:
|
|
3
|
-
- name: 'db'
|
|
4
|
-
path: './'
|
|
5
|
-
engine: 'postgresql'
|
|
6
|
-
schema: './migrations/'
|
|
7
|
-
queries: './queries/'
|
|
8
|
-
emit_json_tags: true
|
|
9
|
-
emit_empty_slices: true
|
|
10
|
-
emit_result_struct_pointers: true
|
|
11
|
-
json_tags_case_style: camel
|
_example/db/todo.sql.go
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
// Code generated by sqlc. DO NOT EDIT.
|
|
2
|
-
// source: todo.sql
|
|
3
|
-
|
|
4
|
-
package db
|
|
5
|
-
|
|
6
|
-
import (
|
|
7
|
-
"context"
|
|
8
|
-
"time"
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
const createTodo = `-- name: CreateTodo :one
|
|
12
|
-
INSERT INTO todos (
|
|
13
|
-
id, text, completed, created_at, updated_at
|
|
14
|
-
) VALUES (
|
|
15
|
-
$1, $2, $3, $4, $5
|
|
16
|
-
) RETURNING id, text, completed, created_at, updated_at
|
|
17
|
-
`
|
|
18
|
-
|
|
19
|
-
type CreateTodoParams struct {
|
|
20
|
-
ID string `json:"id"`
|
|
21
|
-
Text string `json:"text"`
|
|
22
|
-
Completed bool `json:"completed"`
|
|
23
|
-
CreatedAt time.Time `json:"createdAt"`
|
|
24
|
-
UpdatedAt time.Time `json:"updatedAt"`
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
func (q *Queries) CreateTodo(ctx context.Context, arg CreateTodoParams) (*Todo, error) {
|
|
28
|
-
row := q.db.QueryRowContext(ctx, createTodo,
|
|
29
|
-
arg.ID,
|
|
30
|
-
arg.Text,
|
|
31
|
-
arg.Completed,
|
|
32
|
-
arg.CreatedAt,
|
|
33
|
-
arg.UpdatedAt,
|
|
34
|
-
)
|
|
35
|
-
var i Todo
|
|
36
|
-
err := row.Scan(
|
|
37
|
-
&i.ID,
|
|
38
|
-
&i.Text,
|
|
39
|
-
&i.Completed,
|
|
40
|
-
&i.CreatedAt,
|
|
41
|
-
&i.UpdatedAt,
|
|
42
|
-
)
|
|
43
|
-
return &i, err
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const deleteTodo = `-- name: DeleteTodo :exec
|
|
47
|
-
DELETE FROM todos
|
|
48
|
-
WHERE id = $1
|
|
49
|
-
`
|
|
50
|
-
|
|
51
|
-
func (q *Queries) DeleteTodo(ctx context.Context, id string) error {
|
|
52
|
-
_, err := q.db.ExecContext(ctx, deleteTodo, id)
|
|
53
|
-
return err
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const getTodo = `-- name: GetTodo :one
|
|
57
|
-
SELECT id, text, completed, created_at, updated_at FROM todos
|
|
58
|
-
WHERE id = $1 LIMIT 1
|
|
59
|
-
`
|
|
60
|
-
|
|
61
|
-
func (q *Queries) GetTodo(ctx context.Context, id string) (*Todo, error) {
|
|
62
|
-
row := q.db.QueryRowContext(ctx, getTodo, id)
|
|
63
|
-
var i Todo
|
|
64
|
-
err := row.Scan(
|
|
65
|
-
&i.ID,
|
|
66
|
-
&i.Text,
|
|
67
|
-
&i.Completed,
|
|
68
|
-
&i.CreatedAt,
|
|
69
|
-
&i.UpdatedAt,
|
|
70
|
-
)
|
|
71
|
-
return &i, err
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const listTodos = `-- name: ListTodos :many
|
|
75
|
-
SELECT id, text, completed, created_at, updated_at FROM todos
|
|
76
|
-
ORDER BY id LIMIT $1 OFFSET $2
|
|
77
|
-
`
|
|
78
|
-
|
|
79
|
-
type ListTodosParams struct {
|
|
80
|
-
Limit int32 `json:"limit"`
|
|
81
|
-
Offset int32 `json:"offset"`
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
func (q *Queries) ListTodos(ctx context.Context, arg ListTodosParams) ([]*Todo, error) {
|
|
85
|
-
rows, err := q.db.QueryContext(ctx, listTodos, arg.Limit, arg.Offset)
|
|
86
|
-
if err != nil {
|
|
87
|
-
return nil, err
|
|
88
|
-
}
|
|
89
|
-
defer rows.Close()
|
|
90
|
-
items := []*Todo{}
|
|
91
|
-
for rows.Next() {
|
|
92
|
-
var i Todo
|
|
93
|
-
if err := rows.Scan(
|
|
94
|
-
&i.ID,
|
|
95
|
-
&i.Text,
|
|
96
|
-
&i.Completed,
|
|
97
|
-
&i.CreatedAt,
|
|
98
|
-
&i.UpdatedAt,
|
|
99
|
-
); err != nil {
|
|
100
|
-
return nil, err
|
|
101
|
-
}
|
|
102
|
-
items = append(items, &i)
|
|
103
|
-
}
|
|
104
|
-
if err := rows.Close(); err != nil {
|
|
105
|
-
return nil, err
|
|
106
|
-
}
|
|
107
|
-
if err := rows.Err(); err != nil {
|
|
108
|
-
return nil, err
|
|
109
|
-
}
|
|
110
|
-
return items, nil
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const updateTodo = `-- name: UpdateTodo :one
|
|
114
|
-
UPDATE todos
|
|
115
|
-
SET
|
|
116
|
-
completed = $2,
|
|
117
|
-
updated_at = $3
|
|
118
|
-
WHERE id = $1
|
|
119
|
-
RETURNING id, text, completed, created_at, updated_at
|
|
120
|
-
`
|
|
121
|
-
|
|
122
|
-
type UpdateTodoParams struct {
|
|
123
|
-
ID string `json:"id"`
|
|
124
|
-
Completed bool `json:"completed"`
|
|
125
|
-
UpdatedAt time.Time `json:"updatedAt"`
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
func (q *Queries) UpdateTodo(ctx context.Context, arg UpdateTodoParams) (*Todo, error) {
|
|
129
|
-
row := q.db.QueryRowContext(ctx, updateTodo, arg.ID, arg.Completed, arg.UpdatedAt)
|
|
130
|
-
var i Todo
|
|
131
|
-
err := row.Scan(
|
|
132
|
-
&i.ID,
|
|
133
|
-
&i.Text,
|
|
134
|
-
&i.Completed,
|
|
135
|
-
&i.CreatedAt,
|
|
136
|
-
&i.UpdatedAt,
|
|
137
|
-
)
|
|
138
|
-
return &i, err
|
|
139
|
-
}
|
_example/makefile
CHANGED
|
@@ -1,19 +1,11 @@
|
|
|
1
1
|
setup:
|
|
2
|
-
go install github.com/kyleconroy/sqlc/cmd/sqlc@v1.13.0
|
|
3
|
-
go install github.com/amacneil/dbmate@v1.12.1
|
|
4
2
|
go install github.com/mitranim/gow@latest
|
|
5
3
|
go install github.com/pyros2097/gromer/cmd/gromer@latest
|
|
6
|
-
docker pull postgres:14.1
|
|
7
|
-
docker run --name postgres141 -p 5432:5432 -e POSTGRES_PASSWORD=demo -d postgres:14.1
|
|
8
4
|
|
|
9
|
-
generate: export DATABASE_URL=postgres://postgres:demo@127.0.0.1:5432/postgres?sslmode=disable
|
|
10
|
-
|
|
5
|
+
update:
|
|
11
|
-
sqlc generate -f db/sqlc.yaml
|
|
12
6
|
gromer -pkg github.com/pyros2097/gromer/_example
|
|
13
|
-
dbmate migrate
|
|
14
7
|
|
|
15
8
|
run: export PORT=3000
|
|
16
|
-
run: export DATABASE_URL=postgres://postgres:demo@127.0.0.1:5432/postgres?sslmode=disable
|
|
17
9
|
run:
|
|
18
10
|
gow run main.go
|
|
19
11
|
|
|
@@ -25,6 +17,5 @@ build:
|
|
|
25
17
|
docker-build:
|
|
26
18
|
docker build -f ../_example/Dockerfile -t example-app:develop ../
|
|
27
19
|
|
|
28
|
-
docker-run: export DATABASE_URL=postgres://postgres:demo@docker.for.mac.host.internal:5432/postgres?sslmode=disable
|
|
29
20
|
docker-run:
|
|
30
|
-
docker run -p 3000:3000
|
|
21
|
+
docker run -p 3000:3000 example-app:develop
|
_example/pages/api/todos/_todoId_/delete.go
CHANGED
|
@@ -3,7 +3,7 @@ package todos_todoId_
|
|
|
3
3
|
import (
|
|
4
4
|
"context"
|
|
5
5
|
|
|
6
|
-
"github.com/pyros2097/gromer/_example/
|
|
6
|
+
"github.com/pyros2097/gromer/_example/services"
|
|
7
7
|
)
|
|
8
8
|
|
|
9
9
|
func DELETE(ctx context.Context, id string) (string, int, error) {
|
|
@@ -11,7 +11,7 @@ func DELETE(ctx context.Context, id string) (string, int, error) {
|
|
|
11
11
|
if err != nil {
|
|
12
12
|
return "", status, err
|
|
13
13
|
}
|
|
14
|
-
err =
|
|
14
|
+
_, err = services.DeleteTodo(ctx, id)
|
|
15
15
|
if err != nil {
|
|
16
16
|
return id, 500, err
|
|
17
17
|
}
|
_example/pages/api/todos/_todoId_/get.go
CHANGED
|
@@ -2,22 +2,17 @@ package todos_todoId_
|
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
4
|
"context"
|
|
5
|
-
"fmt"
|
|
6
|
-
"strings"
|
|
7
5
|
|
|
8
|
-
"github.com/pyros2097/gromer/_example/
|
|
6
|
+
"github.com/pyros2097/gromer/_example/services"
|
|
9
7
|
)
|
|
10
8
|
|
|
11
9
|
type GetParams struct {
|
|
12
10
|
Show string `json:"show"`
|
|
13
11
|
}
|
|
14
12
|
|
|
15
|
-
func GET(ctx context.Context, id string, params GetParams) (*
|
|
13
|
+
func GET(ctx context.Context, id string, params GetParams) (*services.Todo, int, error) {
|
|
16
|
-
todo, err :=
|
|
14
|
+
todo, err := services.GetTodo(ctx, id)
|
|
17
15
|
if err != nil {
|
|
18
|
-
if strings.Contains(err.Error(), "no rows") {
|
|
19
|
-
return nil, 404, fmt.Errorf("Todo with id '%s' not found", id)
|
|
20
|
-
}
|
|
21
16
|
return nil, 500, err
|
|
22
17
|
}
|
|
23
18
|
if params.Show == "true" {
|
_example/pages/api/todos/_todoId_/put.go
CHANGED
|
@@ -2,24 +2,23 @@ package todos_todoId_
|
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
4
|
"context"
|
|
5
|
-
"time"
|
|
6
5
|
|
|
7
|
-
"github.com/pyros2097/gromer/_example/
|
|
6
|
+
"github.com/pyros2097/gromer/_example/services"
|
|
8
7
|
)
|
|
9
8
|
|
|
10
9
|
type PutParams struct {
|
|
10
|
+
Text string `json:"text"`
|
|
11
|
-
Completed bool
|
|
11
|
+
Completed bool `json:"completed"`
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
func PUT(ctx context.Context, id string, params PutParams) (*
|
|
14
|
+
func PUT(ctx context.Context, id string, params PutParams) (*services.Todo, int, error) {
|
|
15
15
|
_, status, err := GET(ctx, id, GetParams{})
|
|
16
16
|
if err != nil {
|
|
17
17
|
return nil, status, err
|
|
18
18
|
}
|
|
19
|
-
todo, err :=
|
|
19
|
+
todo, err := services.UpdateTodo(ctx, id, services.UpdateTodoParams{
|
|
20
|
-
|
|
20
|
+
Text: params.Text,
|
|
21
21
|
Completed: params.Completed,
|
|
22
|
-
UpdatedAt: time.Now(),
|
|
23
22
|
})
|
|
24
23
|
if err != nil {
|
|
25
24
|
return nil, 500, err
|
_example/pages/api/todos/get.go
CHANGED
|
@@ -4,22 +4,17 @@ import (
|
|
|
4
4
|
"context"
|
|
5
5
|
|
|
6
6
|
. "github.com/pyros2097/gromer"
|
|
7
|
-
"github.com/pyros2097/gromer/_example/
|
|
7
|
+
"github.com/pyros2097/gromer/_example/services"
|
|
8
8
|
)
|
|
9
9
|
|
|
10
10
|
type GetParams struct {
|
|
11
|
-
Limit
|
|
11
|
+
Limit int `json:"limit"`
|
|
12
|
-
Offset int `json:"offset"`
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
func GET(ctx context.Context, params GetParams) ([]*
|
|
14
|
+
func GET(ctx context.Context, params GetParams) ([]*services.Todo, int, error) {
|
|
16
15
|
limit := Default(params.Limit, 10)
|
|
17
|
-
todos
|
|
16
|
+
todos := services.GetAllTodo(ctx, services.GetAllTodoParams{
|
|
18
|
-
Limit:
|
|
17
|
+
Limit: limit,
|
|
19
|
-
Offset: int32(params.Offset),
|
|
20
18
|
})
|
|
21
|
-
if err != nil {
|
|
22
|
-
return nil, 500, err
|
|
23
|
-
}
|
|
24
19
|
return todos, 200, nil
|
|
25
20
|
}
|
_example/pages/api/todos/post.go
CHANGED
|
@@ -5,15 +5,15 @@ import (
|
|
|
5
5
|
"time"
|
|
6
6
|
|
|
7
7
|
"github.com/google/uuid"
|
|
8
|
-
"github.com/pyros2097/gromer/_example/
|
|
8
|
+
"github.com/pyros2097/gromer/_example/services"
|
|
9
9
|
)
|
|
10
10
|
|
|
11
11
|
type PostParams struct {
|
|
12
12
|
Text string `json:"text"`
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
func POST(ctx context.Context, b PostParams) (*
|
|
15
|
+
func POST(ctx context.Context, b PostParams) (*services.Todo, int, error) {
|
|
16
|
-
todo, err :=
|
|
16
|
+
todo, err := services.CreateTodo(ctx, services.Todo{
|
|
17
17
|
ID: uuid.New().String(),
|
|
18
18
|
Text: b.Text,
|
|
19
19
|
Completed: false,
|
_example/pages/get.go
CHANGED
|
@@ -16,8 +16,7 @@ type GetParams struct {
|
|
|
16
16
|
func GET(ctx context.Context, params GetParams) (HtmlContent, int, error) {
|
|
17
17
|
page := Default(params.Page, 1)
|
|
18
18
|
todos, status, err := todos.GET(ctx, todos.GetParams{
|
|
19
|
-
Limit:
|
|
19
|
+
Limit: page * 10,
|
|
20
|
-
Offset: 10 * (page - 1),
|
|
21
20
|
})
|
|
22
21
|
if err != nil {
|
|
23
22
|
return HtmlErr(status, err)
|
_example/services/todo.go
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// Code generated by sqlc. DO NOT EDIT.
|
|
2
|
+
|
|
3
|
+
package services
|
|
4
|
+
|
|
5
|
+
import (
|
|
6
|
+
"context"
|
|
7
|
+
"errors"
|
|
8
|
+
"time"
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
type Todo struct {
|
|
12
|
+
ID string `json:"id"`
|
|
13
|
+
Text string `json:"text"`
|
|
14
|
+
Completed bool `json:"completed"`
|
|
15
|
+
CreatedAt time.Time `json:"createdAt"`
|
|
16
|
+
UpdatedAt time.Time `json:"updatedAt"`
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
var todos = []*Todo{}
|
|
20
|
+
|
|
21
|
+
func CreateTodo(ctx context.Context, todo Todo) (*Todo, error) {
|
|
22
|
+
todos = append(todos, &todo)
|
|
23
|
+
return &todo, nil
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
type UpdateTodoParams struct {
|
|
27
|
+
Text string `json:"text"`
|
|
28
|
+
Completed bool `json:"completed"`
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
func UpdateTodo(ctx context.Context, id string, params UpdateTodoParams) (*Todo, error) {
|
|
32
|
+
updateIndex := -1
|
|
33
|
+
for i, todo := range todos {
|
|
34
|
+
if todo.ID == id {
|
|
35
|
+
updateIndex = i
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if updateIndex != -1 {
|
|
39
|
+
todos[updateIndex].Text = params.Text
|
|
40
|
+
todos[updateIndex].Completed = params.Completed
|
|
41
|
+
todos[updateIndex].UpdatedAt = time.Now()
|
|
42
|
+
return todos[updateIndex], nil
|
|
43
|
+
}
|
|
44
|
+
return nil, errors.New("Todo not found")
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
func DeleteTodo(ctx context.Context, id string) (string, error) {
|
|
48
|
+
deleteIndex := -1
|
|
49
|
+
for i, todo := range todos {
|
|
50
|
+
if todo.ID == id {
|
|
51
|
+
deleteIndex = i
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if deleteIndex != -1 {
|
|
55
|
+
todos = append(todos[:deleteIndex], todos[deleteIndex+1:]...)
|
|
56
|
+
return id, nil
|
|
57
|
+
}
|
|
58
|
+
return "", errors.New("Todo not found")
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
func GetTodo(ctx context.Context, id string) (*Todo, error) {
|
|
62
|
+
for _, todo := range todos {
|
|
63
|
+
if todo.ID == id {
|
|
64
|
+
return todo, nil
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return nil, errors.New("Todo not found")
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
type GetAllTodoParams struct {
|
|
72
|
+
Limit int `json:"limit"`
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
func GetAllTodo(ctx context.Context, params GetAllTodoParams) []*Todo {
|
|
76
|
+
return todos
|
|
77
|
+
}
|