@nakedev/go-scaffold 0.5.4 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -2
- package/dist/commands/auth.js +6 -1
- package/dist/commands/check.js +5 -1
- package/dist/commands/method.js +27 -1
- package/dist/index.js +20 -6
- package/dist/prompts/auth-wizard.js +33 -1
- package/dist/templates/create-manifest.js +8 -0
- package/dist/templates/rbac-manifest.js +1 -0
- package/dist/utils/hexagonal-method-patcher.js +79 -20
- package/package.json +1 -1
- package/templates/add/auth/docs/login.yaml.hbs +9 -1
- package/templates/add/auth/internal/app/user/adapters/inbound/http/handler.go.hbs +12 -2
- package/templates/add/auth/internal/app/user/adapters/outbound/postgres/model.go.hbs +1 -0
- package/templates/add/auth/internal/app/user/adapters/outbound/postgres/repository.go.hbs +97 -13
- package/templates/add/auth/internal/app/user/adapters/outbound/postgres/repository_test.go.hbs +169 -5
- package/templates/add/auth/internal/app/user/application/local_auth.go.hbs +44 -2
- package/templates/add/auth/internal/app/user/application/recovery_service.go.hbs +2 -1
- package/templates/add/auth/internal/app/user/application/service.go.hbs +1 -1
- package/templates/add/auth/internal/app/user/application/service_test.go.hbs +71 -12
- package/templates/add/auth/internal/app/user/application/user_query.go.hbs +5 -4
- package/templates/add/auth/internal/app/user/domain/errors.go.hbs +4 -0
- package/templates/add/auth/internal/app/user/ports/repository.go.hbs +21 -3
- package/templates/add/auth/migrations/create_login_throttle.up.sql.hbs +10 -0
- package/templates/add/rbac/docs/roles.yaml.hbs +2 -1
- package/templates/add/rbac/docs/users.yaml.hbs +2 -1
- package/templates/add/rbac/internal/app/role/adapters/inbound/http/dto.go.hbs +52 -0
- package/templates/add/rbac/internal/app/role/adapters/inbound/http/handler.go.hbs +18 -13
- package/templates/add/rbac/internal/app/role/adapters/outbound/postgres/repository.go.hbs +21 -4
- package/templates/add/rbac/internal/app/role/application/dto.go.hbs +19 -11
- package/templates/add/rbac/internal/app/role/application/service.go.hbs +6 -6
- package/templates/add/rbac/internal/app/role/application/service_test.go.hbs +19 -1
- package/templates/add/rbac/internal/app/role/ports/repository.go.hbs +13 -1
- package/templates/create/base/.claude/skills/go-scaffold/SKILL.md.hbs +1 -1
- package/templates/create/base/AGENTS.md.hbs +9 -1
- package/templates/create/base/README.md.hbs +2 -1
- package/templates/create/base/internal/shared/dbq/dbq.go.hbs +47 -0
- package/templates/create/base/internal/shared/dbq/dbq_test.go.hbs +66 -0
- package/templates/create/base/internal/shared/pagination/pagination.go.hbs +19 -2
- package/templates/create/features/docs/architecture.md.hbs +9 -6
- package/templates/create/features/docs/common/parameters.yaml.hbs +5 -0
- package/templates/create/features/docs/common/schemas.yaml.hbs +1 -0
- package/templates/create/features/docs/patterns.md.hbs +60 -0
- package/templates/generate/module/docs/collection.yaml.hbs +2 -1
- package/templates/generate/module/hexagonal/adapters/inbound/http/handler.go.hbs +8 -3
- package/templates/generate/module/hexagonal/adapters/outbound/postgres/repository.go.hbs +27 -4
- package/templates/generate/module/hexagonal/application/cqrs_test.go.hbs +3 -3
- package/templates/generate/module/hexagonal/application/queries.crud.go.hbs +3 -3
- package/templates/generate/module/hexagonal/application/service.crud.go.hbs +3 -3
- package/templates/generate/module/hexagonal/application/service_test.go.hbs +4 -3
- package/templates/generate/module/hexagonal/ports/repository.go.hbs +18 -2
|
@@ -47,7 +47,7 @@ internal/
|
|
|
47
47
|
├── platform/ # talks to real external systems
|
|
48
48
|
│ └── database/ # PostgreSQL connection and pool
|
|
49
49
|
├── shared/ # pure logic/framework glue, no I/O
|
|
50
|
-
│ ├── config/ apperror/ dberr/ httpx/ id/
|
|
50
|
+
│ ├── config/ apperror/ dberr/ dbq/ httpx/ id/
|
|
51
51
|
│ └── middleware/ pagination/ tx/
|
|
52
52
|
└── app/ # domain packages (one per feature)
|
|
53
53
|
└── <domain>/
|
|
@@ -129,12 +129,15 @@ call site, no error-shape drift between domains.
|
|
|
129
129
|
- DB errors are classified once in `shared/dberr` (`IsDuplicate`,
|
|
130
130
|
`IsForeignKey`) and mapped to the right HTTP status per domain
|
|
131
131
|
|
|
132
|
-
## 6. Pagination
|
|
132
|
+
## 6. Pagination and Filtering
|
|
133
133
|
|
|
134
|
-
**Decision:** Shared `limit`/`offset` parsing and response envelope
|
|
135
|
-
(`shared/pagination`), used by every list endpoint
|
|
136
|
-
|
|
137
|
-
|
|
134
|
+
**Decision:** Shared `limit`/`offset`/`q` parsing and response envelope
|
|
135
|
+
(`shared/pagination`), used by every list endpoint, with the SQL a filter
|
|
136
|
+
repeats in `shared/dbq`. A list takes one filter struct from `ports/` and
|
|
137
|
+
answers a page plus its total.
|
|
138
|
+
**Rationale:** One implementation, one response shape (`{data, limit, offset,
|
|
139
|
+
total}`) — no per-domain reinvention, and no per-domain LIKE escaping to get
|
|
140
|
+
wrong. See `patterns.md`, "Filtered Lists".
|
|
138
141
|
|
|
139
142
|
## 7. Persistence
|
|
140
143
|
|
|
@@ -250,6 +250,66 @@ those markers** — they're where the next `generate method` call inserts. The
|
|
|
250
250
|
method body is always left as a compiling `TODO` rather than guessing at
|
|
251
251
|
business logic — same spirit as `generate module`'s placeholder fields.
|
|
252
252
|
|
|
253
|
+
## Filtered Lists — one filter struct, a page and its total
|
|
254
|
+
|
|
255
|
+
A `crud`-surface module is generated with this already wired; a module that
|
|
256
|
+
grows a list later copies the same four steps. Nothing about it is magic.
|
|
257
|
+
|
|
258
|
+
**1. Parse at the boundary.** `pagination.Parse(c)` returns `Limit`, `Offset`
|
|
259
|
+
and `Search` (`?q=`, trimmed and capped at 100 runes). Read the filters this
|
|
260
|
+
endpoint owns off the query string beside it. An unreadable filter value means
|
|
261
|
+
*no* filter, not `400` — a list narrows on a best effort.
|
|
262
|
+
|
|
263
|
+
**2. One filter struct, in `ports/`.** `ports.ListFilter` travels whole through
|
|
264
|
+
handler → application → repository, so adding a filter later is one field and
|
|
265
|
+
not a fourth positional argument on three signatures. It lives in `ports/`
|
|
266
|
+
because that is the only package all three may import — `ports` importing
|
|
267
|
+
`application` would be a cycle. Its zero value means "the first page of
|
|
268
|
+
everything".
|
|
269
|
+
|
|
270
|
+
```go
|
|
271
|
+
type ListFilter struct {
|
|
272
|
+
Search string
|
|
273
|
+
Limit int
|
|
274
|
+
Offset int
|
|
275
|
+
// Status, OwnerID, DateFrom … whatever this module actually filters by.
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**3. The repository returns the page *and* the total**, because a client that
|
|
280
|
+
pages needs both and only SQL can answer either:
|
|
281
|
+
|
|
282
|
+
```go
|
|
283
|
+
FindAll(context.Context, ListFilter) ([]domain.Thing, int64, error)
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Build the conditions in a closure and call it once per query — conditions
|
|
287
|
+
accumulate on a `*gorm.DB` value, so a count reusing the page's query object
|
|
288
|
+
silently inherits its `LIMIT`. Use `dbq.Search(q, term, cols...)` for a
|
|
289
|
+
contains-search over columns on the same table, and `dbq.LikePattern(term)`
|
|
290
|
+
when the search spans a subquery or a join. Both escape `%` and `_`, so
|
|
291
|
+
someone typing `50%` searches for `50%` instead of matching every row. Always
|
|
292
|
+
keep a tiebreaker in the sort (`ORDER BY created_at DESC, id`) or two rows
|
|
293
|
+
written in the same instant can swap between page 1 and page 2 — showing one
|
|
294
|
+
twice and hiding the other.
|
|
295
|
+
|
|
296
|
+
The generated `FindAll` calls `dbq.Search` with no columns, which is a no-op:
|
|
297
|
+
`?q=` is accepted and ignored until you name the columns this list is searched
|
|
298
|
+
by. That TODO is the one line standing between the scaffold and a working
|
|
299
|
+
search.
|
|
300
|
+
|
|
301
|
+
**4. Respond with the shared envelope.** `p.ResponseWithTotal(out, total)` —
|
|
302
|
+
`{ data, limit, offset, total }`, the same shape for every resource. Anything
|
|
303
|
+
extra is a named key added to that map and documented in the endpoint's
|
|
304
|
+
OpenAPI file. Reuse `common/parameters.yaml#/Search`, `#/Limit` and `#/Offset`
|
|
305
|
+
for the query parameters.
|
|
306
|
+
|
|
307
|
+
Counts that answer a *different* question from the page — "how many are open
|
|
308
|
+
and how many are closed, whichever tab is showing" — belong beside the
|
|
309
|
+
envelope, not in it, and are computed from the filter minus the field the tabs
|
|
310
|
+
switch. A tab that recounted itself when clicked would always read the same
|
|
311
|
+
number.
|
|
312
|
+
|
|
253
313
|
## Testing Conventions
|
|
254
314
|
|
|
255
315
|
- Unit and integration tests live in the same directory as the code under
|
|
@@ -21,9 +21,10 @@ get:
|
|
|
21
21
|
parameters:
|
|
22
22
|
- $ref: '../common/parameters.yaml#/Limit'
|
|
23
23
|
- $ref: '../common/parameters.yaml#/Offset'
|
|
24
|
+
- $ref: '../common/parameters.yaml#/Search'
|
|
24
25
|
responses:
|
|
25
26
|
"200":
|
|
26
|
-
description: paginated list
|
|
27
|
+
description: "paginated list; narrow it with ?q= and whatever filters this module adds"
|
|
27
28
|
content:
|
|
28
29
|
application/json:
|
|
29
30
|
schema:
|
|
@@ -7,6 +7,7 @@ import (
|
|
|
7
7
|
|
|
8
8
|
"{{goModule}}/internal/app/{{modulePath}}/application"
|
|
9
9
|
"{{goModule}}/internal/app/{{modulePath}}/domain"
|
|
10
|
+
"{{goModule}}/internal/app/{{modulePath}}/ports"
|
|
10
11
|
"{{goModule}}/internal/shared/apperror"
|
|
11
12
|
"{{goModule}}/internal/shared/httpx"
|
|
12
13
|
{{#if auth}} "{{goModule}}/internal/shared/middleware"
|
|
@@ -107,10 +108,14 @@ func (h *Handler) create(c *gin.Context) {
|
|
|
107
108
|
|
|
108
109
|
func (h *Handler) list(c *gin.Context) {
|
|
109
110
|
p := pagination.Parse(c)
|
|
111
|
+
// One struct all the way down, so this module's own filters are read off
|
|
112
|
+
// the query string here and added as fields on ports.ListFilter — never as
|
|
113
|
+
// extra arguments on the three signatures below.
|
|
114
|
+
filter := ports.ListFilter{Search: p.Search, Limit: p.Limit, Offset: p.Offset}
|
|
110
115
|
{{#if cqrs}}
|
|
111
|
-
items, err := h.queries.List(c.Request.Context(),
|
|
116
|
+
items, total, err := h.queries.List(c.Request.Context(), filter)
|
|
112
117
|
{{else}}
|
|
113
|
-
items, err := h.svc.List(c.Request.Context(),
|
|
118
|
+
items, total, err := h.svc.List(c.Request.Context(), filter)
|
|
114
119
|
{{/if}}
|
|
115
120
|
if err != nil {
|
|
116
121
|
c.Error(appError(err))
|
|
@@ -120,7 +125,7 @@ func (h *Handler) list(c *gin.Context) {
|
|
|
120
125
|
for i := range items {
|
|
121
126
|
out[i] = toResponse(application.ToResponse(&items[i]))
|
|
122
127
|
}
|
|
123
|
-
c.JSON(http.StatusOK, p.
|
|
128
|
+
c.JSON(http.StatusOK, p.ResponseWithTotal(out, total))
|
|
124
129
|
}
|
|
125
130
|
|
|
126
131
|
func (h *Handler) get(c *gin.Context) {
|
|
@@ -6,6 +6,7 @@ import (
|
|
|
6
6
|
|
|
7
7
|
"{{goModule}}/internal/app/{{modulePath}}/domain"
|
|
8
8
|
"{{goModule}}/internal/app/{{modulePath}}/ports"
|
|
9
|
+
"{{goModule}}/internal/shared/dbq"
|
|
9
10
|
"{{goModule}}/internal/shared/dberr"
|
|
10
11
|
"{{goModule}}/internal/shared/tx"
|
|
11
12
|
|
|
@@ -30,16 +31,38 @@ func (r *Repository) Create(ctx context.Context, m *domain.{{pascalName}}) error
|
|
|
30
31
|
return nil
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
// FindAll answers one page of the filter and how many rows it matched
|
|
35
|
+
// altogether. Two queries, because a count over a LIMITed query would only
|
|
36
|
+
// ever count the page.
|
|
37
|
+
func (r *Repository) FindAll(ctx context.Context, filter ports.ListFilter) ([]domain.{{pascalName}}, int64, error) {
|
|
38
|
+
// A closure rather than one *gorm.DB reused twice: conditions accumulate
|
|
39
|
+
// on the value, so the count would silently inherit the page's LIMIT.
|
|
40
|
+
matching := func() *gorm.DB {
|
|
41
|
+
q := tx.From(ctx, r.db).WithContext(ctx).Model(&{{pascalName}}Model{})
|
|
42
|
+
// TODO: name the columns this list is searched by. dbq.Search is a
|
|
43
|
+
// no-op until it has at least one, so ?q= is accepted and ignored
|
|
44
|
+
// until then. Add this module's own filters beside it.
|
|
45
|
+
q = dbq.Search(q, filter.Search /*, "name", "code" */)
|
|
46
|
+
return q
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
var total int64
|
|
50
|
+
if err := matching().Count(&total).Error; err != nil {
|
|
51
|
+
return nil, 0, mapDatabaseError(err)
|
|
52
|
+
}
|
|
53
|
+
|
|
34
54
|
var rows []{{pascalName}}Model
|
|
35
|
-
|
|
36
|
-
|
|
55
|
+
// created_at orders it, id breaks the ties: without the tiebreaker two
|
|
56
|
+
// rows written in the same instant can swap between page 1 and page 2,
|
|
57
|
+
// showing one twice and hiding the other.
|
|
58
|
+
if err := matching().Order("created_at desc, id").Limit(filter.Limit).Offset(filter.Offset).Find(&rows).Error; err != nil {
|
|
59
|
+
return nil, 0, mapDatabaseError(err)
|
|
37
60
|
}
|
|
38
61
|
items := make([]domain.{{pascalName}}, len(rows))
|
|
39
62
|
for i := range rows {
|
|
40
63
|
items[i] = *toDomain(&rows[i])
|
|
41
64
|
}
|
|
42
|
-
return items, nil
|
|
65
|
+
return items, total, nil
|
|
43
66
|
}
|
|
44
67
|
|
|
45
68
|
func (r *Repository) FindByID(ctx context.Context, id uuid.UUID) (*domain.{{pascalName}}, error) {
|
|
@@ -15,7 +15,7 @@ import (
|
|
|
15
15
|
// which side of the CQRS boundary was called.
|
|
16
16
|
type repositoryStub struct {
|
|
17
17
|
createFn func(context.Context, *domain.{{pascalName}}) error
|
|
18
|
-
findAllFn func(context.Context,
|
|
18
|
+
findAllFn func(context.Context, ports.ListFilter) ([]domain.{{pascalName}}, int64, error)
|
|
19
19
|
findByIDFn func(context.Context, uuid.UUID) (*domain.{{pascalName}}, error)
|
|
20
20
|
updateFn func(context.Context, *domain.{{pascalName}}) error
|
|
21
21
|
deleteFn func(context.Context, uuid.UUID) error
|
|
@@ -28,11 +28,11 @@ func (s *repositoryStub) Create(ctx context.Context, m *domain.{{pascalName}}) e
|
|
|
28
28
|
}
|
|
29
29
|
return s.createFn(ctx, m)
|
|
30
30
|
}
|
|
31
|
-
func (s *repositoryStub) FindAll(ctx context.Context,
|
|
31
|
+
func (s *repositoryStub) FindAll(ctx context.Context, filter ports.ListFilter) ([]domain.{{pascalName}}, int64, error) {
|
|
32
32
|
if s.findAllFn == nil {
|
|
33
33
|
panic("unexpected repository.FindAll call")
|
|
34
34
|
}
|
|
35
|
-
return s.findAllFn(ctx,
|
|
35
|
+
return s.findAllFn(ctx, filter)
|
|
36
36
|
}
|
|
37
37
|
func (s *repositoryStub) FindByID(ctx context.Context, id uuid.UUID) (*domain.{{pascalName}}, error) {
|
|
38
38
|
if s.findByIDFn == nil {
|
|
@@ -9,7 +9,7 @@ import (
|
|
|
9
9
|
)
|
|
10
10
|
|
|
11
11
|
type QueryPort interface {
|
|
12
|
-
List(context.Context,
|
|
12
|
+
List(context.Context, ports.ListFilter) ([]domain.{{pascalName}}, int64, error)
|
|
13
13
|
Get(context.Context, uuid.UUID) (*domain.{{pascalName}}, error)
|
|
14
14
|
// go-scaffold:query-interface
|
|
15
15
|
}
|
|
@@ -22,8 +22,8 @@ func NewQueryHandler(repo ports.QueryRepository) *QueryHandler {
|
|
|
22
22
|
return &QueryHandler{repo: repo}
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
func (h *QueryHandler) List(ctx context.Context,
|
|
26
|
-
return h.repo.FindAll(ctx,
|
|
25
|
+
func (h *QueryHandler) List(ctx context.Context, filter ports.ListFilter) ([]domain.{{pascalName}}, int64, error) {
|
|
26
|
+
return h.repo.FindAll(ctx, filter)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
func (h *QueryHandler) Get(ctx context.Context, id uuid.UUID) (*domain.{{pascalName}}, error) {
|
|
@@ -13,7 +13,7 @@ import (
|
|
|
13
13
|
|
|
14
14
|
type ServicePort interface {
|
|
15
15
|
Create(context.Context, CreateInput) (*domain.{{pascalName}}, error)
|
|
16
|
-
List(context.Context,
|
|
16
|
+
List(context.Context, ports.ListFilter) ([]domain.{{pascalName}}, int64, error)
|
|
17
17
|
Get(context.Context, uuid.UUID) (*domain.{{pascalName}}, error)
|
|
18
18
|
Update(context.Context, uuid.UUID, UpdateInput) (*domain.{{pascalName}}, error)
|
|
19
19
|
Delete(context.Context, uuid.UUID) error
|
|
@@ -38,8 +38,8 @@ func (s *Service) Create(ctx context.Context, in CreateInput) (*domain.{{pascalN
|
|
|
38
38
|
return m, nil
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
func (s *Service) List(ctx context.Context,
|
|
42
|
-
return s.repo.FindAll(ctx,
|
|
41
|
+
func (s *Service) List(ctx context.Context, filter ports.ListFilter) ([]domain.{{pascalName}}, int64, error) {
|
|
42
|
+
return s.repo.FindAll(ctx, filter)
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
func (s *Service) Get(ctx context.Context, id uuid.UUID) (*domain.{{pascalName}}, error) {
|
|
@@ -5,6 +5,7 @@ import (
|
|
|
5
5
|
"testing"
|
|
6
6
|
|
|
7
7
|
"{{goModule}}/internal/app/{{modulePath}}/domain"
|
|
8
|
+
"{{goModule}}/internal/app/{{modulePath}}/ports"
|
|
8
9
|
|
|
9
10
|
"github.com/google/uuid"
|
|
10
11
|
)
|
|
@@ -15,7 +16,7 @@ import (
|
|
|
15
16
|
// orchestration.
|
|
16
17
|
type repositoryStub struct {
|
|
17
18
|
createFn func(context.Context, *domain.{{pascalName}}) error
|
|
18
|
-
findAllFn func(context.Context,
|
|
19
|
+
findAllFn func(context.Context, ports.ListFilter) ([]domain.{{pascalName}}, int64, error)
|
|
19
20
|
findByIDFn func(context.Context, uuid.UUID) (*domain.{{pascalName}}, error)
|
|
20
21
|
updateFn func(context.Context, *domain.{{pascalName}}) error
|
|
21
22
|
deleteFn func(context.Context, uuid.UUID) error
|
|
@@ -28,11 +29,11 @@ func (s *repositoryStub) Create(ctx context.Context, m *domain.{{pascalName}}) e
|
|
|
28
29
|
}
|
|
29
30
|
return s.createFn(ctx, m)
|
|
30
31
|
}
|
|
31
|
-
func (s *repositoryStub) FindAll(ctx context.Context,
|
|
32
|
+
func (s *repositoryStub) FindAll(ctx context.Context, filter ports.ListFilter) ([]domain.{{pascalName}}, int64, error) {
|
|
32
33
|
if s.findAllFn == nil {
|
|
33
34
|
panic("unexpected repository.FindAll call")
|
|
34
35
|
}
|
|
35
|
-
return s.findAllFn(ctx,
|
|
36
|
+
return s.findAllFn(ctx, filter)
|
|
36
37
|
}
|
|
37
38
|
func (s *repositoryStub) FindByID(ctx context.Context, id uuid.UUID) (*domain.{{pascalName}}, error) {
|
|
38
39
|
if s.findByIDFn == nil {
|
|
@@ -11,10 +11,26 @@ import (
|
|
|
11
11
|
"github.com/google/uuid"
|
|
12
12
|
)
|
|
13
13
|
|
|
14
|
+
// ListFilter is the whole question the list endpoint asks. The zero value is
|
|
15
|
+
// "the first page of everything", so a caller only sets what it narrows by.
|
|
16
|
+
//
|
|
17
|
+
// Put this module's own filters here as fields rather than as arguments: one
|
|
18
|
+
// struct travels handler -> application -> repository, so adding a filter
|
|
19
|
+
// later is a field and not a fourth parameter on three signatures.
|
|
20
|
+
type ListFilter struct {
|
|
21
|
+
// Search is ?q= as shared/pagination parsed it, empty when the caller
|
|
22
|
+
// sent none.
|
|
23
|
+
Search string
|
|
24
|
+
Limit int
|
|
25
|
+
Offset int
|
|
26
|
+
}
|
|
27
|
+
|
|
14
28
|
// Repository is the complete persistence port for service-style modules.
|
|
15
29
|
type Repository interface {
|
|
16
30
|
Create(context.Context, *domain.{{pascalName}}) error
|
|
17
|
-
FindAll
|
|
31
|
+
// FindAll answers one page and the total the filter matched, which is what
|
|
32
|
+
// a client needs to draw "page 3 of 12".
|
|
33
|
+
FindAll(context.Context, ListFilter) ([]domain.{{pascalName}}, int64, error)
|
|
18
34
|
FindByID(context.Context, uuid.UUID) (*domain.{{pascalName}}, error)
|
|
19
35
|
Update(context.Context, *domain.{{pascalName}}) error
|
|
20
36
|
Delete(context.Context, uuid.UUID) error
|
|
@@ -32,7 +48,7 @@ type CommandRepository interface {
|
|
|
32
48
|
}
|
|
33
49
|
|
|
34
50
|
type QueryRepository interface {
|
|
35
|
-
FindAll(context.Context,
|
|
51
|
+
FindAll(context.Context, ListFilter) ([]domain.{{pascalName}}, int64, error)
|
|
36
52
|
FindByID(context.Context, uuid.UUID) (*domain.{{pascalName}}, error)
|
|
37
53
|
// go-scaffold:query-repository-interface
|
|
38
54
|
}
|