aury-boot 0.0.2__py3-none-any.whl → 0.0.3__py3-none-any.whl

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.
Files changed (138) hide show
  1. aury/boot/__init__.py +66 -0
  2. aury/boot/_version.py +2 -2
  3. aury/boot/application/__init__.py +120 -0
  4. aury/boot/application/app/__init__.py +39 -0
  5. aury/boot/application/app/base.py +511 -0
  6. aury/boot/application/app/components.py +434 -0
  7. aury/boot/application/app/middlewares.py +101 -0
  8. aury/boot/application/config/__init__.py +44 -0
  9. aury/boot/application/config/settings.py +663 -0
  10. aury/boot/application/constants/__init__.py +19 -0
  11. aury/boot/application/constants/components.py +50 -0
  12. aury/boot/application/constants/scheduler.py +28 -0
  13. aury/boot/application/constants/service.py +29 -0
  14. aury/boot/application/errors/__init__.py +55 -0
  15. aury/boot/application/errors/chain.py +80 -0
  16. aury/boot/application/errors/codes.py +67 -0
  17. aury/boot/application/errors/exceptions.py +238 -0
  18. aury/boot/application/errors/handlers.py +320 -0
  19. aury/boot/application/errors/response.py +120 -0
  20. aury/boot/application/interfaces/__init__.py +76 -0
  21. aury/boot/application/interfaces/egress.py +224 -0
  22. aury/boot/application/interfaces/ingress.py +98 -0
  23. aury/boot/application/middleware/__init__.py +22 -0
  24. aury/boot/application/middleware/logging.py +451 -0
  25. aury/boot/application/migrations/__init__.py +13 -0
  26. aury/boot/application/migrations/manager.py +685 -0
  27. aury/boot/application/migrations/setup.py +237 -0
  28. aury/boot/application/rpc/__init__.py +63 -0
  29. aury/boot/application/rpc/base.py +108 -0
  30. aury/boot/application/rpc/client.py +294 -0
  31. aury/boot/application/rpc/discovery.py +218 -0
  32. aury/boot/application/scheduler/__init__.py +13 -0
  33. aury/boot/application/scheduler/runner.py +123 -0
  34. aury/boot/application/server/__init__.py +296 -0
  35. aury/boot/commands/__init__.py +30 -0
  36. aury/boot/commands/add.py +76 -0
  37. aury/boot/commands/app.py +105 -0
  38. aury/boot/commands/config.py +177 -0
  39. aury/boot/commands/docker.py +367 -0
  40. aury/boot/commands/docs.py +284 -0
  41. aury/boot/commands/generate.py +1277 -0
  42. aury/boot/commands/init.py +890 -0
  43. aury/boot/commands/migrate/__init__.py +37 -0
  44. aury/boot/commands/migrate/app.py +54 -0
  45. aury/boot/commands/migrate/commands.py +303 -0
  46. aury/boot/commands/scheduler.py +124 -0
  47. aury/boot/commands/server/__init__.py +21 -0
  48. aury/boot/commands/server/app.py +541 -0
  49. aury/boot/commands/templates/generate/api.py.tpl +105 -0
  50. aury/boot/commands/templates/generate/model.py.tpl +17 -0
  51. aury/boot/commands/templates/generate/repository.py.tpl +19 -0
  52. aury/boot/commands/templates/generate/schema.py.tpl +29 -0
  53. aury/boot/commands/templates/generate/service.py.tpl +48 -0
  54. aury/boot/commands/templates/project/CLI.md.tpl +92 -0
  55. aury/boot/commands/templates/project/DEVELOPMENT.md.tpl +1397 -0
  56. aury/boot/commands/templates/project/README.md.tpl +111 -0
  57. aury/boot/commands/templates/project/admin_console_init.py.tpl +50 -0
  58. aury/boot/commands/templates/project/config.py.tpl +30 -0
  59. aury/boot/commands/templates/project/conftest.py.tpl +26 -0
  60. aury/boot/commands/templates/project/env.example.tpl +213 -0
  61. aury/boot/commands/templates/project/gitignore.tpl +128 -0
  62. aury/boot/commands/templates/project/main.py.tpl +41 -0
  63. aury/boot/commands/templates/project/modules/api.py.tpl +19 -0
  64. aury/boot/commands/templates/project/modules/exceptions.py.tpl +84 -0
  65. aury/boot/commands/templates/project/modules/schedules.py.tpl +18 -0
  66. aury/boot/commands/templates/project/modules/tasks.py.tpl +20 -0
  67. aury/boot/commands/worker.py +143 -0
  68. aury/boot/common/__init__.py +35 -0
  69. aury/boot/common/exceptions/__init__.py +114 -0
  70. aury/boot/common/i18n/__init__.py +16 -0
  71. aury/boot/common/i18n/translator.py +272 -0
  72. aury/boot/common/logging/__init__.py +716 -0
  73. aury/boot/contrib/__init__.py +10 -0
  74. aury/boot/contrib/admin_console/__init__.py +18 -0
  75. aury/boot/contrib/admin_console/auth.py +137 -0
  76. aury/boot/contrib/admin_console/discovery.py +69 -0
  77. aury/boot/contrib/admin_console/install.py +172 -0
  78. aury/boot/contrib/admin_console/utils.py +44 -0
  79. aury/boot/domain/__init__.py +79 -0
  80. aury/boot/domain/exceptions/__init__.py +132 -0
  81. aury/boot/domain/models/__init__.py +51 -0
  82. aury/boot/domain/models/base.py +69 -0
  83. aury/boot/domain/models/mixins.py +135 -0
  84. aury/boot/domain/models/models.py +96 -0
  85. aury/boot/domain/pagination/__init__.py +279 -0
  86. aury/boot/domain/repository/__init__.py +23 -0
  87. aury/boot/domain/repository/impl.py +423 -0
  88. aury/boot/domain/repository/interceptors.py +47 -0
  89. aury/boot/domain/repository/interface.py +106 -0
  90. aury/boot/domain/repository/query_builder.py +348 -0
  91. aury/boot/domain/service/__init__.py +11 -0
  92. aury/boot/domain/service/base.py +73 -0
  93. aury/boot/domain/transaction/__init__.py +404 -0
  94. aury/boot/infrastructure/__init__.py +104 -0
  95. aury/boot/infrastructure/cache/__init__.py +31 -0
  96. aury/boot/infrastructure/cache/backends.py +348 -0
  97. aury/boot/infrastructure/cache/base.py +68 -0
  98. aury/boot/infrastructure/cache/exceptions.py +37 -0
  99. aury/boot/infrastructure/cache/factory.py +94 -0
  100. aury/boot/infrastructure/cache/manager.py +274 -0
  101. aury/boot/infrastructure/database/__init__.py +39 -0
  102. aury/boot/infrastructure/database/config.py +71 -0
  103. aury/boot/infrastructure/database/exceptions.py +44 -0
  104. aury/boot/infrastructure/database/manager.py +317 -0
  105. aury/boot/infrastructure/database/query_tools/__init__.py +164 -0
  106. aury/boot/infrastructure/database/strategies/__init__.py +198 -0
  107. aury/boot/infrastructure/di/__init__.py +15 -0
  108. aury/boot/infrastructure/di/container.py +393 -0
  109. aury/boot/infrastructure/events/__init__.py +33 -0
  110. aury/boot/infrastructure/events/bus.py +362 -0
  111. aury/boot/infrastructure/events/config.py +52 -0
  112. aury/boot/infrastructure/events/consumer.py +134 -0
  113. aury/boot/infrastructure/events/middleware.py +51 -0
  114. aury/boot/infrastructure/events/models.py +63 -0
  115. aury/boot/infrastructure/monitoring/__init__.py +529 -0
  116. aury/boot/infrastructure/scheduler/__init__.py +19 -0
  117. aury/boot/infrastructure/scheduler/exceptions.py +37 -0
  118. aury/boot/infrastructure/scheduler/manager.py +478 -0
  119. aury/boot/infrastructure/storage/__init__.py +38 -0
  120. aury/boot/infrastructure/storage/base.py +164 -0
  121. aury/boot/infrastructure/storage/exceptions.py +37 -0
  122. aury/boot/infrastructure/storage/factory.py +88 -0
  123. aury/boot/infrastructure/tasks/__init__.py +24 -0
  124. aury/boot/infrastructure/tasks/config.py +45 -0
  125. aury/boot/infrastructure/tasks/constants.py +37 -0
  126. aury/boot/infrastructure/tasks/exceptions.py +37 -0
  127. aury/boot/infrastructure/tasks/manager.py +490 -0
  128. aury/boot/testing/__init__.py +24 -0
  129. aury/boot/testing/base.py +122 -0
  130. aury/boot/testing/client.py +163 -0
  131. aury/boot/testing/factory.py +154 -0
  132. aury/boot/toolkit/__init__.py +21 -0
  133. aury/boot/toolkit/http/__init__.py +367 -0
  134. {aury_boot-0.0.2.dist-info → aury_boot-0.0.3.dist-info}/METADATA +3 -2
  135. aury_boot-0.0.3.dist-info/RECORD +137 -0
  136. aury_boot-0.0.2.dist-info/RECORD +0 -5
  137. {aury_boot-0.0.2.dist-info → aury_boot-0.0.3.dist-info}/WHEEL +0 -0
  138. {aury_boot-0.0.2.dist-info → aury_boot-0.0.3.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,320 @@
1
+ """错误处理器实现。
2
+
3
+ 提供责任链模式的错误处理器。
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from abc import ABC, abstractmethod
9
+ from typing import TYPE_CHECKING
10
+
11
+ from fastapi import HTTPException, Request, status
12
+ from fastapi.responses import JSONResponse
13
+ from pydantic import ValidationError
14
+ from sqlalchemy.exc import IntegrityError, SQLAlchemyError
15
+
16
+ from aury.boot.common.exceptions import FoundationError
17
+ from aury.boot.common.logging import logger
18
+ from aury.boot.domain.exceptions import (
19
+ ModelError,
20
+ ServiceException,
21
+ )
22
+ from aury.boot.domain.exceptions import (
23
+ VersionConflictError as DomainVersionConflictError,
24
+ )
25
+ from aury.boot.infrastructure.database.exceptions import (
26
+ DatabaseError as InfraDatabaseError,
27
+ )
28
+
29
+ from ..interfaces.egress import ResponseBuilder
30
+ from .exceptions import BaseError, BusinessError, VersionConflictError
31
+ from .response import ErrorDetail
32
+
33
+
34
+ class ErrorHandler(ABC):
35
+ """错误处理器抽象基类 - 责任链模式。"""
36
+
37
+ def __init__(self) -> None:
38
+ """初始化处理器。"""
39
+ self._next_handler: ErrorHandler | None = None
40
+
41
+ def set_next(self, handler: ErrorHandler) -> ErrorHandler:
42
+ """设置下一个处理器。
43
+
44
+ Args:
45
+ handler: 下一个处理器
46
+
47
+ Returns:
48
+ ErrorHandler: 下一个处理器(支持链式调用)
49
+ """
50
+ self._next_handler = handler
51
+ return handler
52
+
53
+ @abstractmethod
54
+ def can_handle(self, exception: Exception) -> bool:
55
+ """判断是否可以处理该异常。
56
+
57
+ Args:
58
+ exception: 异常对象
59
+
60
+ Returns:
61
+ bool: 是否可以处理
62
+ """
63
+ pass
64
+
65
+ @abstractmethod
66
+ async def handle(self, exception: Exception, request: Request) -> JSONResponse:
67
+ """处理异常。
68
+
69
+ Args:
70
+ exception: 异常对象
71
+ request: 请求对象
72
+
73
+ Returns:
74
+ JSONResponse: 响应对象
75
+ """
76
+ pass
77
+
78
+ async def process(self, exception: Exception, request: Request) -> JSONResponse:
79
+ """处理异常(责任链入口)。
80
+
81
+ Args:
82
+ exception: 异常对象
83
+ request: 请求对象
84
+
85
+ Returns:
86
+ JSONResponse: 响应对象
87
+ """
88
+ if self.can_handle(exception):
89
+ return await self.handle(exception, request)
90
+
91
+ if self._next_handler:
92
+ return await self._next_handler.process(exception, request)
93
+
94
+ # 默认处理
95
+ return await self._default_handle(exception, request)
96
+
97
+ async def _default_handle(self, exception: Exception, request: Request) -> JSONResponse:
98
+ """默认异常处理。"""
99
+ logger.exception(f"未处理的异常: {request.method} {request.url.path}")
100
+
101
+ response = ResponseBuilder.fail(
102
+ message="服务器内部错误",
103
+ code=-1,
104
+ )
105
+ return JSONResponse(
106
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
107
+ content=response.model_dump(mode="json"),
108
+ )
109
+
110
+
111
+ class BaseErrorHandler(ErrorHandler):
112
+ """自定义基础异常处理器。"""
113
+
114
+ def can_handle(self, exception: Exception) -> bool:
115
+ """判断是否为自定义异常。"""
116
+ return isinstance(exception, BaseError)
117
+
118
+ async def handle(self, exception: BaseError, request: Request) -> JSONResponse:
119
+ """处理自定义异常。"""
120
+ logger.warning(f"业务异常: {exception}")
121
+
122
+ errors = [detail.model_dump() for detail in exception.details] if exception.details else None
123
+
124
+ response = ResponseBuilder.fail(
125
+ message=exception.message,
126
+ code=int(exception.code.value),
127
+ errors=errors,
128
+ )
129
+
130
+ # metadata 放入 details 字段
131
+ if exception.metadata:
132
+ response.details = exception.metadata
133
+
134
+ return JSONResponse(
135
+ status_code=exception.status_code,
136
+ content=response.model_dump(mode="json"),
137
+ )
138
+
139
+
140
+ class HTTPExceptionHandler(ErrorHandler):
141
+ """FastAPI HTTP异常处理器。"""
142
+
143
+ def can_handle(self, exception: Exception) -> bool:
144
+ """判断是否为HTTP异常。"""
145
+ return isinstance(exception, HTTPException)
146
+
147
+ async def handle(self, exception: HTTPException, request: Request) -> JSONResponse:
148
+ """处理HTTP异常。"""
149
+ logger.warning(f"HTTP异常: {exception.status_code} - {exception.detail}")
150
+
151
+ response = ResponseBuilder.fail(
152
+ message=exception.detail,
153
+ code=exception.status_code,
154
+ )
155
+
156
+ return JSONResponse(
157
+ status_code=exception.status_code,
158
+ content=response.model_dump(mode="json"),
159
+ )
160
+
161
+
162
+ class ValidationErrorHandler(ErrorHandler):
163
+ """Pydantic验证异常处理器。"""
164
+
165
+ def can_handle(self, exception: Exception) -> bool:
166
+ """判断是否为验证异常。"""
167
+ return isinstance(exception, ValidationError)
168
+
169
+ async def handle(self, exception: Exception, request: Request) -> JSONResponse:
170
+ """处理验证异常。"""
171
+ logger.warning(f"数据验证失败: {exception}")
172
+
173
+ errors = []
174
+ for error in exception.errors():
175
+ errors.append({
176
+ "field": ".".join(str(loc) for loc in error["loc"]),
177
+ "message": error["msg"],
178
+ "type": error["type"],
179
+ })
180
+
181
+ response = ResponseBuilder.fail(
182
+ message="数据验证失败",
183
+ code=400,
184
+ errors=errors,
185
+ )
186
+
187
+ return JSONResponse(
188
+ status_code=status.HTTP_400_BAD_REQUEST,
189
+ content=response.model_dump(mode="json"),
190
+ )
191
+
192
+
193
+ class ServiceErrorHandler(ErrorHandler):
194
+ """服务层异常处理器。
195
+
196
+ 处理 Domain 层的 ServiceException。
197
+ """
198
+
199
+ def can_handle(self, exception: Exception) -> bool:
200
+ """判断是否为服务层异常。"""
201
+ return isinstance(exception, ServiceException)
202
+
203
+ async def handle(self, exception: Exception, request: Request) -> JSONResponse:
204
+ """处理服务层异常。"""
205
+ if not isinstance(exception, ServiceException):
206
+ return await self._default_handle(exception, request)
207
+
208
+ logger.warning(f"服务层异常: {exception}")
209
+
210
+ # 直接使用 ServiceException 的信息
211
+ response = ResponseBuilder.fail(
212
+ message=exception.message,
213
+ code=400, # 服务层异常默认 400
214
+ )
215
+
216
+ # 构建 details
217
+ details: dict = {}
218
+ if exception.code:
219
+ details["code"] = exception.code
220
+ if exception.metadata:
221
+ details.update(exception.metadata)
222
+ if details:
223
+ response.details = details
224
+
225
+ return JSONResponse(
226
+ status_code=status.HTTP_400_BAD_REQUEST,
227
+ content=response.model_dump(mode="json"),
228
+ )
229
+
230
+
231
+ class DatabaseErrorHandler(ErrorHandler):
232
+ """数据库异常处理器。
233
+
234
+ 处理数据库相关错误,包括 Domain 层的异常。
235
+ """
236
+
237
+ def can_handle(self, exception: Exception) -> bool:
238
+ """判断是否为数据库异常。"""
239
+ return isinstance(exception, SQLAlchemyError | ModelError | InfraDatabaseError | FoundationError)
240
+
241
+ async def handle(self, exception: Exception, request: Request) -> JSONResponse:
242
+ """处理数据库异常。"""
243
+ # 处理 Domain 层的 VersionConflictError
244
+ if isinstance(exception, DomainVersionConflictError):
245
+ # 转换为应用层异常
246
+ app_error = VersionConflictError.from_domain_exception(exception)
247
+ response = ResponseBuilder.fail(
248
+ message=app_error.message,
249
+ code=app_error.status_code,
250
+ details=[ErrorDetail(
251
+ message=app_error.message,
252
+ code=app_error.code.value,
253
+ )],
254
+ )
255
+ return JSONResponse(
256
+ status_code=app_error.status_code,
257
+ content=response.model_dump(mode="json"),
258
+ )
259
+
260
+ # 处理唯一约束冲突(如重复的 email、username 等)
261
+ if isinstance(exception, IntegrityError):
262
+ logger.warning(f"数据库完整性约束冲突: {exception}")
263
+
264
+ # 解析错误信息,提取字段名
265
+ error_msg = str(exception.orig) if exception.orig else str(exception)
266
+ field_name = None
267
+
268
+ # 尝试从错误信息中提取字段名
269
+ if "unique constraint" in error_msg.lower() or "duplicate key" in error_msg.lower():
270
+ # PostgreSQL: Key (email)=(xxx) already exists
271
+ # MySQL: Duplicate entry 'xxx' for key 'users.email'
272
+ import re
273
+ # PostgreSQL 格式
274
+ match = re.search(r"Key \((\w+)\)", error_msg)
275
+ if match:
276
+ field_name = match.group(1)
277
+ else:
278
+ # MySQL 格式
279
+ match = re.search(r"for key ['\"]?\w+\.(\w+)['\"]?", error_msg, re.IGNORECASE)
280
+ if match:
281
+ field_name = match.group(1)
282
+
283
+ if field_name:
284
+ message = f"{field_name} 已存在"
285
+ else:
286
+ message = "数据已存在,请检查唯一字段"
287
+
288
+ response = ResponseBuilder.fail(
289
+ message=message,
290
+ code=409,
291
+ )
292
+
293
+ return JSONResponse(
294
+ status_code=status.HTTP_409_CONFLICT,
295
+ content=response.model_dump(mode="json"),
296
+ )
297
+
298
+ # 处理其他数据库错误
299
+ logger.exception(f"数据库错误: {request.method} {request.url.path}")
300
+
301
+ response = ResponseBuilder.fail(
302
+ message="数据库操作失败",
303
+ code=500,
304
+ )
305
+
306
+ return JSONResponse(
307
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
308
+ content=response.model_dump(mode="json"),
309
+ )
310
+
311
+
312
+ __all__ = [
313
+ "BaseErrorHandler",
314
+ "DatabaseErrorHandler",
315
+ "ErrorHandler",
316
+ "HTTPExceptionHandler",
317
+ "ServiceErrorHandler",
318
+ "ValidationErrorHandler",
319
+ ]
320
+
@@ -0,0 +1,120 @@
1
+ """错误响应模型(接口层)。
2
+
3
+ 提供用于 HTTP API 响应的错误详情模型。
4
+ 这是接口层的数据模型,用于序列化和传输。
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Any, ClassVar
10
+
11
+ from pydantic import BaseModel, ConfigDict, Field
12
+
13
+
14
+ class ErrorDetail(BaseModel):
15
+ """错误详情模型(Pydantic)。
16
+
17
+ 支持两种错误类型:
18
+ 1. 字段错误:field不为空,表示特定字段的验证错误
19
+ 2. 通用错误:field为空,表示系统级或业务级错误
20
+
21
+ 使用示例:
22
+ # 字段验证错误
23
+ ErrorDetail(
24
+ field="username",
25
+ message="用户名格式不正确",
26
+ code="INVALID_FORMAT",
27
+ location="body"
28
+ )
29
+
30
+ # 通用业务错误
31
+ ErrorDetail(
32
+ message="库存不足",
33
+ code="INSUFFICIENT_STOCK"
34
+ )
35
+
36
+ # 系统错误
37
+ ErrorDetail(
38
+ message="数据库连接失败",
39
+ code="DB_CONNECTION_ERROR"
40
+ )
41
+ """
42
+
43
+ message: str = Field(..., description="错误消息")
44
+ code: str | None = Field(None, description="错误代码")
45
+ field: str | None = Field(None, description="错误字段(仅字段验证错误)")
46
+ location: str | None = Field(None, description="错误位置(如:body, query, path)")
47
+ value: Any | None = Field(None, description="导致错误的值")
48
+
49
+ @classmethod
50
+ def field_error(
51
+ cls,
52
+ field: str,
53
+ message: str,
54
+ code: str | None = None,
55
+ location: str = "body",
56
+ value: Any | None = None,
57
+ ) -> "ErrorDetail":
58
+ """创建字段验证错误。
59
+
60
+ Args:
61
+ field: 字段名
62
+ message: 错误消息
63
+ code: 错误代码
64
+ location: 错误位置
65
+ value: 错误值
66
+
67
+ Returns:
68
+ ErrorDetail: 错误详情对象
69
+ """
70
+ return cls(
71
+ message=message,
72
+ code=code,
73
+ field=field,
74
+ location=location,
75
+ value=value,
76
+ )
77
+
78
+ @classmethod
79
+ def generic_error(
80
+ cls,
81
+ message: str,
82
+ code: str | None = None,
83
+ ) -> "ErrorDetail":
84
+ """创建通用错误。
85
+
86
+ Args:
87
+ message: 错误消息
88
+ code: 错误代码
89
+
90
+ Returns:
91
+ ErrorDetail: 错误详情对象
92
+ """
93
+ return cls(
94
+ message=message,
95
+ code=code,
96
+ )
97
+
98
+ model_config = ConfigDict(
99
+ json_schema_extra={
100
+ "examples": [
101
+ {
102
+ "message": "用户名格式不正确",
103
+ "code": "INVALID_FORMAT",
104
+ "field": "username",
105
+ "location": "body",
106
+ "value": "user@123"
107
+ },
108
+ {
109
+ "message": "库存不足",
110
+ "code": "INSUFFICIENT_STOCK"
111
+ }
112
+ ]
113
+ }
114
+ )
115
+
116
+
117
+ __all__ = [
118
+ "ErrorDetail",
119
+ ]
120
+
@@ -0,0 +1,76 @@
1
+ """接口层模块。
2
+
3
+ 提供API定义,包括:
4
+ - 错误处理
5
+ - 请求模型(Ingress)
6
+ - 响应模型(Egress)
7
+ """
8
+
9
+ # 错误处理已移至 application.errors
10
+ from ..errors import (
11
+ AlreadyExistsError,
12
+ BaseError,
13
+ BusinessError,
14
+ DatabaseError,
15
+ ErrorCode,
16
+ ErrorDetail,
17
+ ErrorHandler,
18
+ ErrorHandlerChain,
19
+ ForbiddenError,
20
+ NotFoundError,
21
+ UnauthorizedError,
22
+ ValidationError,
23
+ VersionConflictError,
24
+ global_exception_handler,
25
+ )
26
+ from .egress import (
27
+ BaseResponse,
28
+ CountResponse,
29
+ ErrorResponse,
30
+ IDResponse,
31
+ Pagination,
32
+ PaginationResponse,
33
+ ResponseBuilder,
34
+ SuccessResponse,
35
+ )
36
+ from .ingress import (
37
+ BaseRequest,
38
+ FilterRequest,
39
+ ListRequest,
40
+ PaginationRequest,
41
+ SortOrder,
42
+ )
43
+
44
+ __all__ = [
45
+ "AlreadyExistsError",
46
+ "BaseError",
47
+ # 请求模型
48
+ "BaseRequest",
49
+ # 响应模型
50
+ "BaseResponse",
51
+ "BusinessError",
52
+ "CountResponse",
53
+ "DatabaseError",
54
+ # 错误处理
55
+ "ErrorCode",
56
+ "ErrorDetail",
57
+ "ErrorHandler",
58
+ "ErrorHandlerChain",
59
+ "ErrorResponse",
60
+ "FilterRequest",
61
+ "ForbiddenError",
62
+ "IDResponse",
63
+ "ListRequest",
64
+ "NotFoundError",
65
+ "Pagination",
66
+ "PaginationRequest",
67
+ "PaginationResponse",
68
+ "ResponseBuilder",
69
+ "SortOrder",
70
+ "SuccessResponse",
71
+ "UnauthorizedError",
72
+ "ValidationError",
73
+ "VersionConflictError",
74
+ "global_exception_handler",
75
+ ]
76
+