jararaca 0.3.14__py3-none-any.whl → 0.3.16__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.
Potentially problematic release.
This version of jararaca might be problematic. Click here for more details.
- README.md +1 -0
- jararaca/__init__.py +3 -0
- jararaca/messagebus/decorators.py +6 -3
- jararaca/tools/typescript/decorators.py +46 -0
- jararaca/tools/typescript/interface_parser.py +8 -2
- {jararaca-0.3.14.dist-info → jararaca-0.3.16.dist-info}/METADATA +2 -1
- {jararaca-0.3.14.dist-info → jararaca-0.3.16.dist-info}/RECORD +11 -11
- pyproject.toml +41 -1
- {jararaca-0.3.14.dist-info → jararaca-0.3.16.dist-info}/LICENSE +0 -0
- {jararaca-0.3.14.dist-info → jararaca-0.3.16.dist-info}/WHEEL +0 -0
- {jararaca-0.3.14.dist-info → jararaca-0.3.16.dist-info}/entry_points.txt +0 -0
README.md
CHANGED
|
@@ -37,6 +37,7 @@ Jararaca is an async-first microservice framework designed to simplify the devel
|
|
|
37
37
|
- Command-line tool for generating TypeScript types
|
|
38
38
|
- Support for REST endpoints, WebSocket events, and message bus payloads
|
|
39
39
|
- Type-safe frontend-backend communication
|
|
40
|
+
- **`@ExposeType` decorator** - Explicitly expose types for TypeScript generation without needing them in endpoints
|
|
40
41
|
|
|
41
42
|
### Hexagonal Architecture
|
|
42
43
|
- Clear separation of concerns
|
jararaca/__init__.py
CHANGED
|
@@ -171,6 +171,7 @@ if TYPE_CHECKING:
|
|
|
171
171
|
from .scheduler.decorators import ScheduledAction
|
|
172
172
|
from .tools.app_config.interceptor import AppConfigurationInterceptor
|
|
173
173
|
from .tools.typescript.decorators import (
|
|
174
|
+
ExposeType,
|
|
174
175
|
MutationEndpoint,
|
|
175
176
|
QueryEndpoint,
|
|
176
177
|
SplitInputOutput,
|
|
@@ -279,6 +280,7 @@ if TYPE_CHECKING:
|
|
|
279
280
|
"MessageBusPublisherInterceptor",
|
|
280
281
|
"RedisWebSocketConnectionBackend",
|
|
281
282
|
"AppConfigurationInterceptor",
|
|
283
|
+
"ExposeType",
|
|
282
284
|
"QueryEndpoint",
|
|
283
285
|
"MutationEndpoint",
|
|
284
286
|
"SplitInputOutput",
|
|
@@ -510,6 +512,7 @@ _dynamic_imports: "dict[str, tuple[str, str, str | None]]" = {
|
|
|
510
512
|
"tools.app_config.interceptor",
|
|
511
513
|
None,
|
|
512
514
|
),
|
|
515
|
+
"ExposeType": (__SPEC_PARENT__, "tools.typescript.decorators", None),
|
|
513
516
|
"QueryEndpoint": (__SPEC_PARENT__, "tools.typescript.decorators", None),
|
|
514
517
|
"MutationEndpoint": (__SPEC_PARENT__, "tools.typescript.decorators", None),
|
|
515
518
|
"SplitInputOutput": (__SPEC_PARENT__, "tools.typescript.decorators", None),
|
|
@@ -11,6 +11,8 @@ from jararaca.scheduler.decorators import ScheduledAction, ScheduledActionData
|
|
|
11
11
|
|
|
12
12
|
DECORATED_FUNC = TypeVar("DECORATED_FUNC", bound=Callable[..., Any])
|
|
13
13
|
DECORATED_T = TypeVar("DECORATED_T", bound=Any)
|
|
14
|
+
INSTANCE_T = TypeVar("INSTANCE_T", bound=Any)
|
|
15
|
+
RETURN_T = TypeVar("RETURN_T", bound=Any)
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
class MessageHandler(Generic[INHERITS_MESSAGE_CO]):
|
|
@@ -35,8 +37,9 @@ class MessageHandler(Generic[INHERITS_MESSAGE_CO]):
|
|
|
35
37
|
self.name = name
|
|
36
38
|
|
|
37
39
|
def __call__(
|
|
38
|
-
self,
|
|
39
|
-
|
|
40
|
+
self,
|
|
41
|
+
func: Callable[[INSTANCE_T, MessageOf[INHERITS_MESSAGE_CO]], Awaitable[None]],
|
|
42
|
+
) -> Callable[[INSTANCE_T, MessageOf[INHERITS_MESSAGE_CO]], Awaitable[None]]:
|
|
40
43
|
|
|
41
44
|
MessageHandler[Any].register(func, self)
|
|
42
45
|
|
|
@@ -52,7 +55,7 @@ class MessageHandler(Generic[INHERITS_MESSAGE_CO]):
|
|
|
52
55
|
|
|
53
56
|
@staticmethod
|
|
54
57
|
def get_message_incoming(
|
|
55
|
-
func: Callable[[MessageOf[Any]], Awaitable[
|
|
58
|
+
func: Callable[[Any, MessageOf[Any]], Awaitable[None]],
|
|
56
59
|
) -> "MessageHandler[Message] | None":
|
|
57
60
|
if not hasattr(func, MessageHandler.MESSAGE_INCOMING_ATTR):
|
|
58
61
|
return None
|
|
@@ -93,3 +93,49 @@ class SplitInputOutput:
|
|
|
93
93
|
Check if the Pydantic model is marked for split interface generation.
|
|
94
94
|
"""
|
|
95
95
|
return getattr(cls, SplitInputOutput.METADATA_KEY, False)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class ExposeType:
|
|
99
|
+
"""
|
|
100
|
+
Decorator to explicitly expose types for TypeScript interface generation.
|
|
101
|
+
|
|
102
|
+
Use this decorator to include types in the generated TypeScript output without
|
|
103
|
+
needing them as request/response bodies or indirect dependencies.
|
|
104
|
+
|
|
105
|
+
Example:
|
|
106
|
+
@ExposeType()
|
|
107
|
+
class UserRole(BaseModel):
|
|
108
|
+
id: str
|
|
109
|
+
name: str
|
|
110
|
+
|
|
111
|
+
# This ensures UserRole interface is generated even if it's not
|
|
112
|
+
# directly referenced in any REST endpoint
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
METADATA_KEY = "__jararaca_expose_type__"
|
|
116
|
+
_exposed_types: set[type] = set()
|
|
117
|
+
|
|
118
|
+
def __init__(self) -> None:
|
|
119
|
+
pass
|
|
120
|
+
|
|
121
|
+
def __call__(self, cls: type[BASEMODEL_T]) -> type[BASEMODEL_T]:
|
|
122
|
+
"""
|
|
123
|
+
Decorate the type to mark it for explicit TypeScript generation.
|
|
124
|
+
"""
|
|
125
|
+
setattr(cls, self.METADATA_KEY, True)
|
|
126
|
+
ExposeType._exposed_types.add(cls)
|
|
127
|
+
return cls
|
|
128
|
+
|
|
129
|
+
@staticmethod
|
|
130
|
+
def is_exposed_type(cls: type) -> bool:
|
|
131
|
+
"""
|
|
132
|
+
Check if the type is marked for explicit exposure.
|
|
133
|
+
"""
|
|
134
|
+
return getattr(cls, ExposeType.METADATA_KEY, False)
|
|
135
|
+
|
|
136
|
+
@staticmethod
|
|
137
|
+
def get_all_exposed_types() -> set[type]:
|
|
138
|
+
"""
|
|
139
|
+
Get all types that have been marked for explicit exposure.
|
|
140
|
+
"""
|
|
141
|
+
return ExposeType._exposed_types.copy()
|
|
@@ -36,6 +36,7 @@ from jararaca.presentation.websocket.websocket_interceptor import (
|
|
|
36
36
|
WebSocketMessageWrapper,
|
|
37
37
|
)
|
|
38
38
|
from jararaca.tools.typescript.decorators import (
|
|
39
|
+
ExposeType,
|
|
39
40
|
MutationEndpoint,
|
|
40
41
|
QueryEndpoint,
|
|
41
42
|
SplitInputOutput,
|
|
@@ -661,6 +662,9 @@ def write_microservice_to_typescript_interface(
|
|
|
661
662
|
websocket_registries: set[RegisterWebSocketMessage] = set()
|
|
662
663
|
mapped_types_set.add(WebSocketMessageWrapper)
|
|
663
664
|
|
|
665
|
+
# Add all explicitly exposed types
|
|
666
|
+
mapped_types_set.update(ExposeType.get_all_exposed_types())
|
|
667
|
+
|
|
664
668
|
for controller in microservice.controllers:
|
|
665
669
|
rest_controller = RestController.get_controller(controller)
|
|
666
670
|
|
|
@@ -700,7 +704,7 @@ def write_microservice_to_typescript_interface(
|
|
|
700
704
|
|
|
701
705
|
// noinspection JSUnusedGlobalSymbols
|
|
702
706
|
|
|
703
|
-
import { HttpService, HttpBackend, HttpBackendRequest, ResponseType, createClassQueryHooks , createClassMutationHooks, createClassInfiniteQueryHooks, paginationModelByFirstArgPaginationFilter } from "@jararaca/core";
|
|
707
|
+
import { HttpService, HttpBackend, HttpBackendRequest, ResponseType, createClassQueryHooks , createClassMutationHooks, createClassInfiniteQueryHooks, paginationModelByFirstArgPaginationFilter, recursiveCamelToSnakeCase } from "@jararaca/core";
|
|
704
708
|
|
|
705
709
|
function makeFormData(data: Record<string, any>): FormData {
|
|
706
710
|
const formData = new FormData();
|
|
@@ -723,7 +727,9 @@ function* genFormDataValue(value: any): any {
|
|
|
723
727
|
} else if (typeof value === "object" && value.constructor === Object) {
|
|
724
728
|
// Stringify plain objects as JSON
|
|
725
729
|
// formData.append(key, JSON.stringify(value));
|
|
726
|
-
yield JSON.stringify(
|
|
730
|
+
yield JSON.stringify(
|
|
731
|
+
recursiveCamelToSnakeCase(value)
|
|
732
|
+
);
|
|
727
733
|
} else {
|
|
728
734
|
// For primitives (string, number, boolean), append as-is
|
|
729
735
|
yield value;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: jararaca
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.16
|
|
4
4
|
Summary: A simple and fast API framework for Python
|
|
5
5
|
Home-page: https://github.com/LuscasLeo/jararaca
|
|
6
6
|
Author: Lucas S
|
|
@@ -74,6 +74,7 @@ Jararaca is an async-first microservice framework designed to simplify the devel
|
|
|
74
74
|
- Command-line tool for generating TypeScript types
|
|
75
75
|
- Support for REST endpoints, WebSocket events, and message bus payloads
|
|
76
76
|
- Type-safe frontend-backend communication
|
|
77
|
+
- **`@ExposeType` decorator** - Explicitly expose types for TypeScript generation without needing them in endpoints
|
|
77
78
|
|
|
78
79
|
### Hexagonal Architecture
|
|
79
80
|
- Clear separation of concerns
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
2
|
-
README.md,sha256=
|
|
3
|
-
pyproject.toml,sha256=
|
|
4
|
-
jararaca/__init__.py,sha256=
|
|
2
|
+
README.md,sha256=YmCngjU8llW0l7L3tuXkkfr8qH7V9aBMgfp2jEzeiKg,3517
|
|
3
|
+
pyproject.toml,sha256=Qn_u7qKJbAetHjXlx0gwVX_gnib76NkIQd6zQMYfkro,2832
|
|
4
|
+
jararaca/__init__.py,sha256=IMnvfDoyNWTGVittF_wq2Uxtv_BY_wLN5Om6C3vUsCw,22302
|
|
5
5
|
jararaca/__main__.py,sha256=-O3vsB5lHdqNFjUtoELDF81IYFtR-DSiiFMzRaiSsv4,67
|
|
6
6
|
jararaca/broker_backend/__init__.py,sha256=GzEIuHR1xzgCJD4FE3harNjoaYzxHMHoEL0_clUaC-k,3528
|
|
7
7
|
jararaca/broker_backend/mapper.py,sha256=vTsi7sWpNvlga1PWPFg0rCJ5joJ0cdzykkIc2Tuvenc,696
|
|
@@ -17,7 +17,7 @@ jararaca/lifecycle.py,sha256=qKlzLQQioS8QkxNJ_FC_5WbmT77cNbc_S7OcQeOoHkI,1895
|
|
|
17
17
|
jararaca/messagebus/__init__.py,sha256=5jAqPqdcEMYBfQyfZDWPnplYdrfMyJLMcacf3qLyUhk,56
|
|
18
18
|
jararaca/messagebus/bus_message_controller.py,sha256=Xd_qwnX5jUvgBTCarHR36fvtol9lPTsYp2IIGKyQQaE,1487
|
|
19
19
|
jararaca/messagebus/consumers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
-
jararaca/messagebus/decorators.py,sha256=
|
|
20
|
+
jararaca/messagebus/decorators.py,sha256=P5z0BBL4hJfgCJHKbsDhSZmlRwzV4PlCPKvEZ4sguXM,6013
|
|
21
21
|
jararaca/messagebus/interceptors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
22
|
jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py,sha256=_DEHwIH9LYsA26Hu1mo9oHzLZuATgjilU9E3o-ecDjs,6520
|
|
23
23
|
jararaca/messagebus/interceptors/publisher_interceptor.py,sha256=ojy1bRhqMgrkQljcGGS8cd8-8pUjL8ZHjIUkdmaAnNM,1325
|
|
@@ -69,13 +69,13 @@ jararaca/tools/app_config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
|
|
|
69
69
|
jararaca/tools/app_config/decorators.py,sha256=-ckkMZ1dswOmECdo1rFrZ15UAku--txaNXMp8fd1Ndk,941
|
|
70
70
|
jararaca/tools/app_config/interceptor.py,sha256=HV8h4AxqUc_ACs5do4BSVlyxlRXzx7HqJtoVO9tfRnQ,2611
|
|
71
71
|
jararaca/tools/typescript/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
72
|
-
jararaca/tools/typescript/decorators.py,sha256=
|
|
73
|
-
jararaca/tools/typescript/interface_parser.py,sha256=
|
|
72
|
+
jararaca/tools/typescript/decorators.py,sha256=2NXFI6MiqpjM8rmrje38dR5StRlqdzYOmPASgyLIHeo,4267
|
|
73
|
+
jararaca/tools/typescript/interface_parser.py,sha256=yOSuOXKOeG0soGFo0fKiZIabu4YwnvIKk-Zss8UPAuE,55174
|
|
74
74
|
jararaca/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
75
75
|
jararaca/utils/rabbitmq_utils.py,sha256=ytdAFUyv-OBkaVnxezuJaJoLrmN7giZgtKeet_IsMBs,10918
|
|
76
76
|
jararaca/utils/retry.py,sha256=DzPX_fXUvTqej6BQ8Mt2dvLo9nNlTBm7Kx2pFZ26P2Q,4668
|
|
77
|
-
jararaca-0.3.
|
|
78
|
-
jararaca-0.3.
|
|
79
|
-
jararaca-0.3.
|
|
80
|
-
jararaca-0.3.
|
|
81
|
-
jararaca-0.3.
|
|
77
|
+
jararaca-0.3.16.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
78
|
+
jararaca-0.3.16.dist-info/METADATA,sha256=mIIZae49Gn54udR4m7qk3ZwTjx66iSQpgIp9Abm_Ymo,5149
|
|
79
|
+
jararaca-0.3.16.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
80
|
+
jararaca-0.3.16.dist-info/entry_points.txt,sha256=WIh3aIvz8LwUJZIDfs4EeH3VoFyCGEk7cWJurW38q0I,45
|
|
81
|
+
jararaca-0.3.16.dist-info/RECORD,,
|
pyproject.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "jararaca"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.16"
|
|
4
4
|
description = "A simple and fast API framework for Python"
|
|
5
5
|
authors = ["Lucas S <me@luscasleo.dev>"]
|
|
6
6
|
readme = "README.md"
|
|
@@ -62,6 +62,10 @@ mkdocs-mermaid2-plugin = "^1.2.1"
|
|
|
62
62
|
[tool.poetry.group.dev.dependencies]
|
|
63
63
|
httptools = "^0.6.1"
|
|
64
64
|
httpx = "^0.27.2"
|
|
65
|
+
pytest = "^8.0.0"
|
|
66
|
+
pytest-asyncio = "^0.23.0"
|
|
67
|
+
pytest-cov = "^4.1.0"
|
|
68
|
+
pytest-mock = "^3.12.0"
|
|
65
69
|
|
|
66
70
|
[build-system]
|
|
67
71
|
requires = ["poetry-core"]
|
|
@@ -84,3 +88,39 @@ jararaca = "jararaca.cli:cli"
|
|
|
84
88
|
[[tool.mypy.overrides]]
|
|
85
89
|
module = "mako.*"
|
|
86
90
|
ignore_missing_imports = true
|
|
91
|
+
|
|
92
|
+
[tool.pytest.ini_options]
|
|
93
|
+
testpaths = ["tests"]
|
|
94
|
+
python_files = ["test_*.py"]
|
|
95
|
+
python_classes = ["Test*"]
|
|
96
|
+
python_functions = ["test_*"]
|
|
97
|
+
asyncio_mode = "auto"
|
|
98
|
+
addopts = [
|
|
99
|
+
"--strict-markers",
|
|
100
|
+
"--strict-config",
|
|
101
|
+
"--showlocals",
|
|
102
|
+
]
|
|
103
|
+
markers = [
|
|
104
|
+
"unit: Unit tests",
|
|
105
|
+
"integration: Integration tests",
|
|
106
|
+
"slow: Slow tests",
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
[tool.coverage.run]
|
|
110
|
+
source = ["src/jararaca"]
|
|
111
|
+
omit = [
|
|
112
|
+
"*/tests/*",
|
|
113
|
+
"*/__pycache__/*",
|
|
114
|
+
"*/.venv/*",
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
[tool.coverage.report]
|
|
118
|
+
exclude_lines = [
|
|
119
|
+
"pragma: no cover",
|
|
120
|
+
"def __repr__",
|
|
121
|
+
"raise AssertionError",
|
|
122
|
+
"raise NotImplementedError",
|
|
123
|
+
"if __name__ == .__main__.:",
|
|
124
|
+
"if TYPE_CHECKING:",
|
|
125
|
+
"@abstractmethod",
|
|
126
|
+
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|