Skip to content
This repository was archived by the owner on Aug 18, 2024. It is now read-only.

Commit a18c894

Browse files
committed
WIP
1 parent a5e7d99 commit a18c894

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+580
-260
lines changed

.vscode/settings.json

+17-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,20 @@
1010
"source.organizeImports": "explicit"
1111
}
1212
},
13-
"black-formatter.args": ["--line-length", "88"],
14-
"flake8.args": ["--max-line-length", "88", "--extend-ignore", "E203,E701"],
15-
"isort.args": ["--profile", "black", "--line-length", "88"]
16-
}
13+
"black-formatter.args": [
14+
"--line-length",
15+
"88"
16+
],
17+
"flake8.args": [
18+
"--max-line-length",
19+
"88",
20+
"--extend-ignore",
21+
"E203,E501,E701"
22+
],
23+
"isort.args": [
24+
"--profile",
25+
"black",
26+
"--line-length",
27+
"88"
28+
]
29+
}

base/collection.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package base
22

3-
import "fmt"
3+
import (
4+
"fmt"
5+
)
46

57
func CopySlice[T any](collection []T) []T {
68
ret := make([]T, len(collection))

cmd/serve.go

+9-7
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ import (
1818
authfactory "github.com/twin-te/twinte-back/module/auth/factory"
1919
authrepository "github.com/twin-te/twinte-back/module/auth/repository"
2020
authusecase "github.com/twin-te/twinte-back/module/auth/usecase"
21-
donationmodule "github.com/twin-te/twinte-back/module/donation"
21+
donationfactory "github.com/twin-te/twinte-back/module/donation/factory"
22+
donationgateway "github.com/twin-te/twinte-back/module/donation/gateway"
23+
donationrepository "github.com/twin-te/twinte-back/module/donation/repository"
24+
donationusecase "github.com/twin-te/twinte-back/module/donation/usecase"
2225
schoolcalendarrepository "github.com/twin-te/twinte-back/module/schoolcalendar/repository"
2326
schoolcalendarusecase "github.com/twin-te/twinte-back/module/schoolcalendar/usecase"
2427
timetablefactory "github.com/twin-te/twinte-back/module/timetable/factory"
@@ -57,11 +60,10 @@ var serveCmd = &cobra.Command{
5760
log.Fatalln(err)
5861
}
5962

60-
var dummyDonationUseCase donationmodule.UseCase
61-
// donationFactory := donationfactory.New()
62-
// donationGateway := donationgateway.New()
63-
// donationRepository := donationrepository.New(db)
64-
// donationUseCase := donationusecase.New(accessController, donationFactory, donationGateway, donationRepository)
63+
donationFactory := donationfactory.New()
64+
donationGateway := donationgateway.New()
65+
donationRepository := donationrepository.New(db)
66+
donationUseCase := donationusecase.New(accessController, donationFactory, donationGateway, donationRepository)
6567

6668
schoolcalendarRepository := schoolcalendarrepository.New()
6769
schoolcalendarUseCase := schoolcalendarusecase.New(accessController, schoolcalendarRepository)
@@ -93,7 +95,7 @@ var serveCmd = &cobra.Command{
9395
accessController,
9496
announcementUsecase,
9597
authUseCase,
96-
dummyDonationUseCase,
98+
donationUseCase,
9799
schoolcalendarUseCase,
98100
timetableUseCase,
99101
)

codegen/error/definition.csv

-8
This file was deleted.

codegen/error/definition.py

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from typing import NewType
2+
3+
ConnectErrorCode = NewType("ConnectErrorCode", str)
4+
5+
Canceled = ConnectErrorCode("Canceled")
6+
Unknown = ConnectErrorCode("Unknown")
7+
InvalidArgument = ConnectErrorCode("InvalidArgument")
8+
DeadlineExceeded = ConnectErrorCode("DeadlineExceeded")
9+
NotFound = ConnectErrorCode("NotFound")
10+
AlreadyExists = ConnectErrorCode("AlreadyExists")
11+
PermissionDenied = ConnectErrorCode("PermissionDenied")
12+
ResourceExhausted = ConnectErrorCode("ResourceExhausted")
13+
FailedPrecondition = ConnectErrorCode("FailedPrecondition")
14+
Aborted = ConnectErrorCode("Aborted")
15+
OutOfRange = ConnectErrorCode("OutOfRange")
16+
Unimplemented = ConnectErrorCode("Unimplemented")
17+
Internal = ConnectErrorCode("Internal")
18+
Unavailable = ConnectErrorCode("Unavailable")
19+
DataLoss = ConnectErrorCode("DataLoss")
20+
Unauthenticated = ConnectErrorCode("Unauthenticated")
21+
22+
definition: dict[str, list[tuple[str, ConnectErrorCode]]] = {
23+
"announcement": [
24+
("AnnouncementNotFound", NotFound),
25+
],
26+
"auth": [
27+
("UserAuthenticationAlreadyExists", AlreadyExists),
28+
("UserAuthenticationNotAssociated", FailedPrecondition),
29+
("UserHasAtLeastOneAuthentication", FailedPrecondition),
30+
(
31+
"UserHasAtMostOneAuthenticationFromSameProvider",
32+
FailedPrecondition,
33+
),
34+
],
35+
"donation": [("SubscriptionNotFound", NotFound)],
36+
"schoolcalendar": [
37+
("ModuleNotFound", NotFound),
38+
],
39+
"shared": [
40+
("AlreadyExists", AlreadyExists),
41+
("InvalidArgument", InvalidArgument),
42+
("NotFound", NotFound),
43+
("Unauthenticated", Unauthenticated),
44+
("Unauthorized", PermissionDenied),
45+
],
46+
"timetable": [
47+
("CourseNotFound", NotFound),
48+
("RegisteredCourseAlreadyExists", AlreadyExists),
49+
("RegisteredCourseNotFound", NotFound),
50+
("TagNotFound", NotFound),
51+
],
52+
}

codegen/error/generate.py

+61-47
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,82 @@
1-
import csv
21
import pathlib
2+
import re
33

4-
module_name_to_error_codes: dict[str, list[str]] = {}
5-
error_code_to_description: dict[str, str] = {}
4+
from definition import definition
65

76

8-
def generate_go_code(module_name: str) -> str:
9-
error_codes = module_name_to_error_codes[module_name]
7+
def convert_pascal_case_to_snake_case(s: str) -> str:
8+
"""Convert PascalCase to snake_case.
109
10+
cf. https://stackoverflow.com/questions/1175208/elegant-python-function-to-convert-camelcase-to-snake-case
11+
"""
12+
s = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", s)
13+
s = re.sub("([a-z0-9])([A-Z])", r"\1_\2", s).lower()
14+
return s
15+
16+
17+
def convert_pascal_case_to_upper_snake_case(s: str) -> str:
18+
s = convert_pascal_case_to_snake_case(s)
19+
s = s.upper()
20+
return s
21+
22+
23+
def generate_go_error_definition(module: str) -> str:
1124
ret = f"""// Code generated by codegen/error/generate.py; DO NOT EDIT.
1225
13-
package {module_name}err
26+
package {module}err
1427
1528
import "github.com/twin-te/twinte-back/apperr"
1629
1730
const (
1831
"""
1932

33+
error_codes = [error_code for error_code, _ in definition[module]]
34+
2035
max_length = max(map(len, error_codes))
36+
2137
for error_code in error_codes:
22-
ret += f'\tCode{error_code.ljust(max_length)} apperr.Code = "{module_name}.{error_code}"\n'
38+
ret += f'\tCode{error_code.ljust(max_length)} apperr.Code = "{module}.{error_code}"\n'
2339

2440
ret += """)
2541
"""
2642

2743
return ret
2844

2945

30-
def generate_markdown_list() -> str:
31-
ret = """<!-- Code generated by codegen/error/generate.py; DO NOT EDIT. -->
46+
def generate_go_error_code_map() -> str:
47+
ret = """// Code generated by codegen/error/generate.py; DO NOT EDIT.
3248
33-
## Error Code List
49+
package interceptor
3450
35-
"""
51+
import (
52+
"github.com/bufbuild/connect-go"
53+
"github.com/twin-te/twinte-back/apperr"
54+
""" # noqa: E101, W191
3655

37-
for module_name, error_codes in module_name_to_error_codes.items():
38-
ret += f"""### {module_name}
39-
| Error Code | Description |
40-
| :---: | :---: |
56+
for module in definition.keys():
57+
ret += f""" {module}err "github.com/twin-te/twinte-back/module/{module}/err"
4158
"""
42-
for error_code in error_codes:
43-
description = error_code_to_description[error_code]
44-
ret += f"| `{module_name}.{error_code}` | {description} |\n"
45-
ret += "\n"
46-
47-
return ret
48-
4959

50-
def load_definition() -> None:
51-
definition_file_path = pathlib.Path(__file__).parent.joinpath("definition.csv")
60+
ret += """)
5261
53-
with definition_file_path.open("r") as f:
54-
reader = csv.reader(f)
55-
rows = [row for row in reader][1:] # exclude header
62+
var AppErrorCodeToConnectErrorCode = map[apperr.Code]connect.Code{
63+
"""
64+
for i, module in enumerate(definition):
65+
if i > 0:
66+
ret += "\n"
67+
68+
for app_error_code, connect_error_code in definition[module]:
69+
max_length = max(
70+
[len(app_error_code) for app_error_code, _ in definition[module]]
71+
)
72+
num_spaces = max_length - len(app_error_code)
73+
ret += f""" {module}err.Code{app_error_code}:{" " * num_spaces} connect.Code{connect_error_code},
74+
"""
5675

57-
for module_name, error_code, description in rows:
58-
if module_name not in module_name_to_error_codes:
59-
module_name_to_error_codes[module_name] = []
60-
module_name_to_error_codes[module_name].append(error_code)
61-
error_code_to_description[error_code] = description
76+
ret += """}
77+
"""
6278

63-
print(f"load definition from {definition_file_path.as_posix()}")
79+
return ret
6480

6581

6682
def output_to_file(output_file_path: pathlib.Path, content: str) -> None:
@@ -71,22 +87,20 @@ def output_to_file(output_file_path: pathlib.Path, content: str) -> None:
7187

7288

7389
def main() -> None:
74-
load_definition()
75-
76-
# Go Code
77-
for module_name in module_name_to_error_codes:
78-
output_go_file_path = (
79-
pathlib.Path(__file__)
80-
.parents[2]
81-
.joinpath(f"module/{module_name}/err/code.gen.go")
82-
)
83-
content = generate_go_code(module_name)
90+
root_path = pathlib.Path(__file__).parents[2]
91+
92+
# Generate go error definition
93+
for module in definition.keys():
94+
output_go_file_path = root_path.joinpath(f"module/{module}/err/code_gen.go")
95+
content = generate_go_error_definition(module)
8496
output_to_file(output_go_file_path, content)
8597

86-
# Markdown List
87-
output_markdown_list_path = pathlib.Path(__file__).parent.joinpath("list.gen.md")
88-
content = generate_markdown_list()
89-
output_to_file(output_markdown_list_path, content)
98+
# Generate go error code map
99+
content = generate_go_error_code_map()
100+
output_file_path = root_path.joinpath(
101+
"handler/common/interceptor/error_code_map_gen.go"
102+
)
103+
output_to_file(output_file_path, content)
90104

91105

92106
if __name__ == "__main__":

codegen/error/list.gen.md

-19
This file was deleted.

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ require (
1111
github.com/oapi-codegen/runtime v1.1.1
1212
github.com/rs/cors v1.10.1
1313
github.com/samber/lo v1.39.0
14+
github.com/samber/mo v1.11.0
1415
github.com/spf13/cobra v1.8.0
1516
github.com/stretchr/testify v1.8.4
1617
github.com/stripe/stripe-go/v76 v76.18.0

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU
138138
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
139139
github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA=
140140
github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
141+
github.com/samber/mo v1.11.0 h1:ZOiSkrGGpNhVv/1dxP02risztdMTIwE8KSW9OG4k5bY=
142+
github.com/samber/mo v1.11.0/go.mod h1:BfkrCPuYzVG3ZljnZB783WIJIGk1mcZr9c9CPf8tAxs=
141143
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
142144
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
143145
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=

handler/common/interceptor/connect.go

+2-12
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"github.com/twin-te/twinte-back/apperr"
1111
authmodule "github.com/twin-te/twinte-back/module/auth"
1212
"github.com/twin-te/twinte-back/module/shared/domain/idtype"
13-
sharederr "github.com/twin-te/twinte-back/module/shared/err"
1413
)
1514

1615
func getSessionIDFromHeader(header http.Header) (id idtype.SessionID, ok bool) {
@@ -51,17 +50,8 @@ func NewErrorInterceptor() connect.UnaryInterceptorFunc {
5150
) (connect.AnyResponse, error) {
5251
res, err := next(ctx, req)
5352
if aerr, ok := apperr.As(err); ok {
54-
switch aerr.Code {
55-
case sharederr.CodeAlreadyExists:
56-
err = connect.NewError(connect.CodeAlreadyExists, err)
57-
case sharederr.CodeInvalidArgument:
58-
err = connect.NewError(connect.CodeInvalidArgument, err)
59-
case sharederr.CodeNotFound:
60-
err = connect.NewError(connect.CodeNotFound, err)
61-
case sharederr.CodeUnauthorized:
62-
err = connect.NewError(connect.CodePermissionDenied, err)
63-
case sharederr.CodeUnauthenticated:
64-
err = connect.NewError(connect.CodeUnauthenticated, err)
53+
if connectErrorCode, ok := AppErrorCodeToConnectErrorCode[aerr.Code]; ok {
54+
err = connect.NewError(connectErrorCode, err)
6555
}
6656
}
6757
return res, err

handler/common/interceptor/error_code_map_gen.go

+38
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

module/announcement/err/code_gen.go

+9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)