@nakedev/go-scaffold 0.4.3 → 0.5.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 +567 -513
- package/dist/commands/auth.js +12 -1
- package/dist/commands/check.js +281 -0
- package/dist/commands/create.js +2 -1
- package/dist/commands/generate.js +5 -2
- package/dist/commands/method.js +66 -70
- package/dist/commands/observability.js +4 -53
- package/dist/commands/rbac.js +19 -8
- package/dist/commands/undo.js +6 -3
- package/dist/commands/worker.js +14 -4
- package/dist/index.js +13 -1
- package/dist/templates/auth-manifest.js +46 -45
- package/dist/templates/create-manifest.js +4 -0
- package/dist/templates/module-manifest.js +82 -60
- package/dist/templates/rbac-manifest.js +15 -11
- package/dist/templates/worker-manifest.js +4 -1
- package/dist/types.js +2 -0
- package/dist/utils/auth-patcher.js +22 -22
- package/dist/utils/config.js +24 -5
- package/dist/utils/docs-patcher.js +68 -0
- package/dist/utils/hexagonal-method-patcher.js +334 -0
- package/dist/utils/main-patcher.js +3 -3
- package/dist/utils/module-location.js +17 -11
- package/dist/utils/platform-patcher.js +27 -0
- package/dist/utils/rbac-patcher.js +73 -216
- package/package.json +1 -1
- package/templates/add/auth/cmd/seed/main.go.hbs +2 -0
- package/templates/add/auth/internal/app/user/{browser_policy.go.hbs → adapters/inbound/http/browser_policy.go.hbs} +3 -3
- package/templates/add/auth/internal/app/user/adapters/inbound/http/dto.go.hbs +159 -0
- package/templates/add/auth/internal/app/user/{handler.go.hbs → adapters/inbound/http/handler.go.hbs} +103 -8
- package/templates/add/auth/internal/app/user/{handler_local.go.hbs → adapters/inbound/http/handler_local.go.hbs} +8 -7
- package/templates/add/auth/internal/app/user/{handler_mfa.go.hbs → adapters/inbound/http/handler_mfa.go.hbs} +6 -6
- package/templates/add/auth/internal/app/user/{handler_oauth.go.hbs → adapters/inbound/http/handler_oauth.go.hbs} +17 -17
- package/templates/add/auth/internal/app/user/{handler_recovery.go.hbs → adapters/inbound/http/handler_recovery.go.hbs} +4 -4
- package/templates/add/auth/internal/app/user/{handler_test.go.hbs → adapters/inbound/http/handler_test.go.hbs} +52 -31
- package/templates/add/auth/internal/app/user/{handler_user.go.hbs → adapters/inbound/http/handler_user.go.hbs} +4 -4
- package/templates/add/auth/internal/app/user/{session_cookie.go.hbs → adapters/inbound/http/session_cookie.go.hbs} +5 -3
- package/templates/add/auth/internal/app/user/adapters/outbound/password/bcrypt.go.hbs +35 -0
- package/templates/add/auth/internal/app/user/adapters/outbound/password/bcrypt_test.go.hbs +20 -0
- package/templates/add/auth/internal/app/user/{mfa_store.go.hbs → adapters/outbound/postgres/mfa_store.go.hbs} +22 -20
- package/templates/add/auth/internal/app/user/{mfa_store_test.go.hbs → adapters/outbound/postgres/mfa_store_test.go.hbs} +7 -7
- package/templates/add/auth/internal/app/user/adapters/outbound/postgres/model.go.hbs +84 -0
- package/templates/add/auth/internal/app/user/adapters/outbound/postgres/repository.go.hbs +211 -0
- package/templates/add/auth/internal/app/user/{repository_test.go.hbs → adapters/outbound/postgres/repository_test.go.hbs} +18 -19
- package/templates/add/auth/internal/app/user/{tokenstore_pg.go.hbs → adapters/outbound/postgres/tokenstore_pg.go.hbs} +36 -32
- package/templates/add/auth/internal/app/user/{tokenstore_pg_test.go.hbs → adapters/outbound/postgres/tokenstore_pg_test.go.hbs} +10 -3
- package/templates/add/auth/internal/app/user/{tokenstore_recovery.go.hbs → adapters/outbound/postgres/tokenstore_recovery.go.hbs} +29 -3
- package/templates/add/auth/internal/app/user/{tokenstore_redis.go.hbs → adapters/outbound/redis/tokenstore.go.hbs} +43 -36
- package/templates/add/auth/internal/app/user/{tokenstore_redis_test.go.hbs → adapters/outbound/redis/tokenstore_test.go.hbs} +14 -3
- package/templates/add/auth/internal/app/user/application/contracts.go.hbs +52 -0
- package/templates/add/auth/internal/app/user/application/dto.go.hbs +75 -0
- package/templates/add/auth/internal/app/user/application/errors.go.hbs +62 -0
- package/templates/add/auth/internal/app/user/{external_login.go.hbs → application/external_login.go.hbs} +30 -40
- package/templates/add/auth/internal/app/user/{jwt.go.hbs → application/jwt.go.hbs} +6 -3
- package/templates/add/auth/internal/app/user/{local_auth.go.hbs → application/local_auth.go.hbs} +17 -19
- package/templates/add/auth/internal/app/user/{mfa_service.go.hbs → application/mfa_service.go.hbs} +27 -28
- package/templates/add/auth/internal/app/user/{mfa_service_test.go.hbs → application/mfa_service_test.go.hbs} +12 -11
- package/templates/add/auth/internal/app/user/application/oauth.go.hbs +3 -3
- package/templates/add/auth/internal/app/user/{provider_test.go.hbs → application/provider_test.go.hbs} +55 -56
- package/templates/add/auth/internal/app/user/application/recovery.go.hbs +16 -47
- package/templates/add/auth/internal/app/user/{recovery_service.go.hbs → application/recovery_service.go.hbs} +13 -15
- package/templates/add/auth/internal/app/user/application/service.go.hbs +145 -0
- package/templates/add/auth/internal/app/user/{service_test.go.hbs → application/service_test.go.hbs} +94 -75
- package/templates/add/auth/internal/app/user/{sessions.go.hbs → application/sessions.go.hbs} +14 -14
- package/templates/add/auth/internal/app/user/application/tokenstore_ports.go.hbs +14 -0
- package/templates/add/auth/internal/app/user/{user_query.go.hbs → application/user_query.go.hbs} +16 -16
- package/templates/add/auth/internal/app/user/composition.go.hbs +89 -86
- package/templates/add/auth/internal/app/user/domain/entity.go.hbs +41 -0
- package/templates/add/auth/internal/app/user/domain/errors.go.hbs +32 -0
- package/templates/add/auth/internal/app/user/ports/password.go.hbs +9 -0
- package/templates/add/auth/internal/app/user/ports/repository.go.hbs +90 -0
- package/templates/add/auth/migrations/create_auth_tokens.up.sql.hbs +1 -1
- package/templates/add/auth/migrations/create_login_throttle.up.sql.hbs +1 -1
- package/templates/add/auth/migrations/create_users.up.sql.hbs +2 -1
- package/templates/add/rbac/internal/app/role/adapters/inbound/http/handler.go.hbs +142 -0
- package/templates/add/rbac/internal/app/role/adapters/inbound/http/handler_test.go.hbs +19 -0
- package/templates/add/rbac/internal/app/role/adapters/outbound/postgres/model.go.hbs +48 -0
- package/templates/add/rbac/internal/app/role/adapters/outbound/postgres/repository.go.hbs +127 -0
- package/templates/add/rbac/internal/app/role/{repository_test.go.hbs → adapters/outbound/postgres/repository_test.go.hbs} +8 -8
- package/templates/add/rbac/internal/app/role/application/dto.go.hbs +47 -0
- package/templates/add/rbac/internal/app/role/application/errors.go.hbs +19 -0
- package/templates/add/rbac/internal/app/role/application/service.go.hbs +157 -0
- package/templates/add/rbac/internal/app/role/{service_test.go.hbs → application/service_test.go.hbs} +26 -19
- package/templates/add/rbac/internal/app/role/composition.go.hbs +23 -10
- package/templates/add/rbac/internal/app/role/domain/entity.go.hbs +23 -0
- package/templates/add/rbac/internal/app/role/domain/errors.go.hbs +26 -0
- package/templates/add/rbac/internal/app/role/ports/repository.go.hbs +25 -0
- package/templates/add/rbac/migrations/add_roles.down.sql.hbs +3 -11
- package/templates/add/rbac/migrations/add_roles.up.sql.hbs +17 -6
- package/templates/add/worker/internal/platform/queue/river_test.go.hbs +84 -0
- package/templates/create/base/.claude/skills/go-scaffold/SKILL.md.hbs +54 -36
- package/templates/create/base/.golangci.yml.hbs +2 -2
- package/templates/create/base/AGENTS.md.hbs +55 -31
- package/templates/create/base/README.md.hbs +77 -22
- package/templates/create/base/cmd/api/wiring.go.hbs +3 -2
- package/templates/create/base/internal/composition/doc.go.hbs +7 -0
- package/templates/create/features/docs/architecture.md.hbs +64 -26
- package/templates/create/features/docs/patterns.md.hbs +117 -90
- package/templates/create/features/docs/techstack.md.hbs +17 -2
- package/templates/generate/module/hexagonal/adapters/inbound/http/dto.go.hbs +45 -0
- package/templates/generate/module/hexagonal/adapters/inbound/http/dto.minimal.go.hbs +28 -0
- package/templates/generate/module/hexagonal/adapters/inbound/http/handler.go.hbs +182 -0
- package/templates/generate/module/hexagonal/adapters/inbound/http/handler.minimal.go.hbs +83 -0
- package/templates/generate/module/hexagonal/adapters/inbound/http/handler_crud_test.go.hbs +18 -0
- package/templates/generate/module/hexagonal/adapters/inbound/http/handler_test.go.hbs +30 -0
- package/templates/generate/module/hexagonal/adapters/outbound/postgres/model.go.hbs +37 -0
- package/templates/generate/module/hexagonal/adapters/outbound/postgres/repository.go.hbs +95 -0
- package/templates/generate/module/{repository_test.go.hbs → hexagonal/adapters/outbound/postgres/repository_test.go.hbs} +8 -8
- package/templates/generate/module/hexagonal/application/commands.crud.go.hbs +54 -0
- package/templates/generate/module/hexagonal/application/commands.go.hbs +25 -0
- package/templates/generate/module/hexagonal/application/cqrs_test.go.hbs +66 -0
- package/templates/generate/module/hexagonal/application/dto.go.hbs +35 -0
- package/templates/generate/module/hexagonal/application/dto.minimal.go.hbs +25 -0
- package/templates/generate/module/hexagonal/application/queries.crud.go.hbs +33 -0
- package/templates/generate/module/hexagonal/application/queries.go.hbs +25 -0
- package/templates/generate/module/hexagonal/application/service.crud.go.hbs +73 -0
- package/templates/generate/module/hexagonal/application/service.go.hbs +29 -0
- package/templates/generate/module/hexagonal/application/service_test.go.hbs +62 -0
- package/templates/generate/module/hexagonal/composition.go.hbs +27 -0
- package/templates/generate/module/hexagonal/domain/entity.go.hbs +20 -0
- package/templates/generate/module/hexagonal/domain/errors.go.hbs +11 -0
- package/templates/generate/module/hexagonal/ports/repository.go.hbs +38 -0
- package/templates/generate/module/migration.up.sql.hbs +1 -1
- package/dist/utils/method-patcher.js +0 -537
- package/templates/add/auth/internal/app/user/contracts.go.hbs +0 -88
- package/templates/add/auth/internal/app/user/dto.go.hbs +0 -134
- package/templates/add/auth/internal/app/user/errors.go.hbs +0 -68
- package/templates/add/auth/internal/app/user/model/authtoken.go.hbs +0 -45
- package/templates/add/auth/internal/app/user/model/identity.go.hbs +0 -32
- package/templates/add/auth/internal/app/user/model/loginthrottle.go.hbs +0 -26
- package/templates/add/auth/internal/app/user/model/mfa_challenge.go.hbs +0 -17
- package/templates/add/auth/internal/app/user/model/mfa_enrollment.go.hbs +0 -20
- package/templates/add/auth/internal/app/user/model/mfa_recovery_code.go.hbs +0 -17
- package/templates/add/auth/internal/app/user/model/user.go.hbs +0 -31
- package/templates/add/auth/internal/app/user/repository.go.hbs +0 -139
- package/templates/add/auth/internal/app/user/service.go.hbs +0 -135
- package/templates/add/auth/internal/app/user/tokenstore.go.hbs +0 -58
- package/templates/add/rbac/internal/app/role/dto.go.hbs +0 -45
- package/templates/add/rbac/internal/app/role/errors.go.hbs +0 -39
- package/templates/add/rbac/internal/app/role/handler.go.hbs +0 -104
- package/templates/add/rbac/internal/app/role/model/permission.go.hbs +0 -12
- package/templates/add/rbac/internal/app/role/model/role.go.hbs +0 -22
- package/templates/add/rbac/internal/app/role/model/role_permission.go.hbs +0 -11
- package/templates/add/rbac/internal/app/role/repository.go.hbs +0 -97
- package/templates/add/rbac/internal/app/role/service.go.hbs +0 -217
- package/templates/generate/module/commands.go.hbs +0 -95
- package/templates/generate/module/composition.go.hbs +0 -23
- package/templates/generate/module/cqrs_test.go.hbs +0 -7
- package/templates/generate/module/dto.go.hbs +0 -36
- package/templates/generate/module/errors.go.hbs +0 -33
- package/templates/generate/module/handler.go.hbs +0 -179
- package/templates/generate/module/handler_test.go.hbs +0 -174
- package/templates/generate/module/minimal/commands.go.hbs +0 -34
- package/templates/generate/module/minimal/dto.go.hbs +0 -28
- package/templates/generate/module/minimal/handler.go.hbs +0 -82
- package/templates/generate/module/minimal/handler_test.go.hbs +0 -10
- package/templates/generate/module/minimal/queries.go.hbs +0 -45
- package/templates/generate/module/minimal/service.go.hbs +0 -71
- package/templates/generate/module/minimal/service_test.go.hbs +0 -77
- package/templates/generate/module/model/model.go.hbs +0 -36
- package/templates/generate/module/queries.go.hbs +0 -62
- package/templates/generate/module/repository.go.hbs +0 -103
- package/templates/generate/module/service.go.hbs +0 -164
- package/templates/generate/module/service_test.go.hbs +0 -161
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
package {{pkg}}
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"context"
|
|
5
|
-
"errors"
|
|
6
|
-
"testing"
|
|
7
|
-
|
|
8
|
-
"{{goModule}}/internal/app/{{modulePath}}/model"
|
|
9
|
-
"{{goModule}}/internal/shared/apperror"
|
|
10
|
-
|
|
11
|
-
"github.com/google/uuid"
|
|
12
|
-
"gorm.io/gorm"
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
// repositoryStub exposes one function per dependency operation. Tests configure
|
|
16
|
-
// only the calls they expect; an unexpected call panics instead of silently
|
|
17
|
-
// returning a shared zero value/error that can hide broken orchestration.
|
|
18
|
-
type repositoryStub struct {
|
|
19
|
-
createFn func(context.Context, *model.{{pascalName}}) error
|
|
20
|
-
findAllFn func(context.Context, int, int) ([]model.{{pascalName}}, error)
|
|
21
|
-
findByIDFn func(context.Context, uuid.UUID) (*model.{{pascalName}}, error)
|
|
22
|
-
updateFn func(context.Context, *model.{{pascalName}}) error
|
|
23
|
-
deleteFn func(context.Context, uuid.UUID) error
|
|
24
|
-
// go-scaffold:repository-stub-fields
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
func (s *repositoryStub) Create(ctx context.Context, m *model.{{pascalName}}) error {
|
|
28
|
-
if s.createFn == nil {
|
|
29
|
-
panic("unexpected repository.Create call")
|
|
30
|
-
}
|
|
31
|
-
return s.createFn(ctx, m)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
func (s *repositoryStub) FindAll(ctx context.Context, limit, offset int) ([]model.{{pascalName}}, error) {
|
|
35
|
-
if s.findAllFn == nil {
|
|
36
|
-
panic("unexpected repository.FindAll call")
|
|
37
|
-
}
|
|
38
|
-
return s.findAllFn(ctx, limit, offset)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
func (s *repositoryStub) FindByID(ctx context.Context, id uuid.UUID) (*model.{{pascalName}}, error) {
|
|
42
|
-
if s.findByIDFn == nil {
|
|
43
|
-
panic("unexpected repository.FindByID call")
|
|
44
|
-
}
|
|
45
|
-
return s.findByIDFn(ctx, id)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
func (s *repositoryStub) Update(ctx context.Context, m *model.{{pascalName}}) error {
|
|
49
|
-
if s.updateFn == nil {
|
|
50
|
-
panic("unexpected repository.Update call")
|
|
51
|
-
}
|
|
52
|
-
return s.updateFn(ctx, m)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
func (s *repositoryStub) Delete(ctx context.Context, id uuid.UUID) error {
|
|
56
|
-
if s.deleteFn == nil {
|
|
57
|
-
panic("unexpected repository.Delete call")
|
|
58
|
-
}
|
|
59
|
-
return s.deleteFn(ctx, id)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// go-scaffold:repository-stub-methods
|
|
63
|
-
|
|
64
|
-
func status(t *testing.T, err error) int {
|
|
65
|
-
t.Helper()
|
|
66
|
-
var appErr *apperror.AppError
|
|
67
|
-
if !errors.As(err, &appErr) {
|
|
68
|
-
t.Fatalf("expected *apperror.AppError, got %T: %v", err, err)
|
|
69
|
-
}
|
|
70
|
-
return appErr.HTTPStatus
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
func TestService_Create_Duplicate(t *testing.T) {
|
|
74
|
-
repo := &repositoryStub{
|
|
75
|
-
createFn: func(context.Context, *model.{{pascalName}}) error {
|
|
76
|
-
return gorm.ErrDuplicatedKey
|
|
77
|
-
},
|
|
78
|
-
}
|
|
79
|
-
svc := NewService(repo)
|
|
80
|
-
|
|
81
|
-
_, err := svc.Create(context.Background(), createInput{})
|
|
82
|
-
|
|
83
|
-
if got := status(t, err); got != 409 {
|
|
84
|
-
t.Fatalf("want 409 conflict, got %d", got)
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
func TestService_Get_NotFound(t *testing.T) {
|
|
89
|
-
repo := &repositoryStub{
|
|
90
|
-
findByIDFn: func(context.Context, uuid.UUID) (*model.{{pascalName}}, error) {
|
|
91
|
-
return nil, gorm.ErrRecordNotFound
|
|
92
|
-
},
|
|
93
|
-
}
|
|
94
|
-
svc := NewService(repo)
|
|
95
|
-
|
|
96
|
-
_, err := svc.Get(context.Background(), uuid.New())
|
|
97
|
-
|
|
98
|
-
if got := status(t, err); got != 404 {
|
|
99
|
-
t.Fatalf("want 404, got %d", got)
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
func TestService_List_DBError_Becomes500(t *testing.T) {
|
|
104
|
-
repo := &repositoryStub{
|
|
105
|
-
findAllFn: func(context.Context, int, int) ([]model.{{pascalName}}, error) {
|
|
106
|
-
return nil, errors.New("connection refused")
|
|
107
|
-
},
|
|
108
|
-
}
|
|
109
|
-
svc := NewService(repo)
|
|
110
|
-
|
|
111
|
-
_, err := svc.List(context.Background(), 20, 0)
|
|
112
|
-
|
|
113
|
-
if got := status(t, err); got != 500 {
|
|
114
|
-
t.Fatalf("want 500, got %d", got)
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// The check that stops one user's save from silently erasing another's: the
|
|
119
|
-
// repository reports the row moved on, the client must see 409 rather than a
|
|
120
|
-
// 500 or, worse, a success.
|
|
121
|
-
func TestService_Update_StaleVersion(t *testing.T) {
|
|
122
|
-
repo := &repositoryStub{
|
|
123
|
-
findByIDFn: func(_ context.Context, id uuid.UUID) (*model.{{pascalName}}, error) {
|
|
124
|
-
return &model.{{pascalName}}{ID: id, Version: 7}, nil
|
|
125
|
-
},
|
|
126
|
-
updateFn: func(context.Context, *model.{{pascalName}}) error {
|
|
127
|
-
return ErrStaleVersion
|
|
128
|
-
},
|
|
129
|
-
}
|
|
130
|
-
svc := NewService(repo)
|
|
131
|
-
|
|
132
|
-
_, err := svc.Update(context.Background(), uuid.New(), updateInput{Version: 3})
|
|
133
|
-
|
|
134
|
-
if got := status(t, err); got != 409 {
|
|
135
|
-
t.Fatalf("want 409 stale, got %d", got)
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// The version compared against the database has to be the one the client sent,
|
|
140
|
-
// not the one just read back — comparing the row against itself would always
|
|
141
|
-
// match and the guard would never fire.
|
|
142
|
-
func TestService_Update_SendsClientVersion(t *testing.T) {
|
|
143
|
-
var seen int
|
|
144
|
-
repo := &repositoryStub{
|
|
145
|
-
findByIDFn: func(_ context.Context, id uuid.UUID) (*model.{{pascalName}}, error) {
|
|
146
|
-
return &model.{{pascalName}}{ID: id, Version: 7}, nil
|
|
147
|
-
},
|
|
148
|
-
updateFn: func(_ context.Context, m *model.{{pascalName}}) error {
|
|
149
|
-
seen = m.Version
|
|
150
|
-
return nil
|
|
151
|
-
},
|
|
152
|
-
}
|
|
153
|
-
svc := NewService(repo)
|
|
154
|
-
|
|
155
|
-
if _, err := svc.Update(context.Background(), uuid.New(), updateInput{Version: 3}); err != nil {
|
|
156
|
-
t.Fatalf("update: %v", err)
|
|
157
|
-
}
|
|
158
|
-
if seen != 3 {
|
|
159
|
-
t.Fatalf("want the client's version 3 to reach the repository, got %d", seen)
|
|
160
|
-
}
|
|
161
|
-
}
|