jararaca 0.2.37a10__py3-none-any.whl → 0.2.37a12__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.
- jararaca/__init__.py +7 -0
- jararaca/cli.py +78 -4
- jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py +66 -11
- jararaca/messagebus/worker.py +11 -11
- jararaca-0.2.37a12.dist-info/METADATA +154 -0
- {jararaca-0.2.37a10.dist-info → jararaca-0.2.37a12.dist-info}/RECORD +9 -12
- {jararaca-0.2.37a10.dist-info → jararaca-0.2.37a12.dist-info}/WHEEL +1 -1
- README.md +0 -243
- jararaca-0.2.37a10.dist-info/LICENSE +0 -674
- jararaca-0.2.37a10.dist-info/METADATA +0 -278
- pyproject.toml +0 -77
- /LICENSE → /jararaca-0.2.37a12.dist-info/LICENSE +0 -0
- {jararaca-0.2.37a10.dist-info → jararaca-0.2.37a12.dist-info}/entry_points.txt +0 -0
jararaca/__init__.py
CHANGED
|
@@ -59,6 +59,7 @@ if TYPE_CHECKING:
|
|
|
59
59
|
from .messagebus.decorators import MessageBusController, MessageHandler
|
|
60
60
|
from .messagebus.interceptors.aiopika_publisher_interceptor import (
|
|
61
61
|
AIOPikaConnectionFactory,
|
|
62
|
+
GenericPoolConfig,
|
|
62
63
|
MessageBusPublisherInterceptor,
|
|
63
64
|
)
|
|
64
65
|
from .messagebus.publisher import use_publisher
|
|
@@ -192,6 +193,7 @@ if TYPE_CHECKING:
|
|
|
192
193
|
"Put",
|
|
193
194
|
"Delete",
|
|
194
195
|
"use_publisher",
|
|
196
|
+
"GenericPoolConfig",
|
|
195
197
|
"AIOPikaConnectionFactory",
|
|
196
198
|
"MessageBusPublisherInterceptor",
|
|
197
199
|
"RedisWebSocketConnectionBackend",
|
|
@@ -221,6 +223,11 @@ _dynamic_imports: "dict[str, tuple[str, str, str | None]]" = {
|
|
|
221
223
|
"messagebus.bus_message_controller",
|
|
222
224
|
None,
|
|
223
225
|
),
|
|
226
|
+
"GenericPoolConfig": (
|
|
227
|
+
__SPEC_PARENT__,
|
|
228
|
+
"messagebus.interceptors.aiopika_publisher_interceptor",
|
|
229
|
+
None,
|
|
230
|
+
),
|
|
224
231
|
"ack": (__SPEC_PARENT__, "messagebus.bus_message_controller", None),
|
|
225
232
|
"nack": (__SPEC_PARENT__, "messagebus.bus_message_controller", None),
|
|
226
233
|
"reject": (__SPEC_PARENT__, "messagebus.bus_message_controller", None),
|
jararaca/cli.py
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import importlib
|
|
2
2
|
import importlib.resources
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
import time
|
|
3
6
|
from codecs import StreamWriter
|
|
4
7
|
from typing import Any
|
|
5
8
|
from urllib.parse import urlparse, urlunsplit
|
|
@@ -208,12 +211,83 @@ def scheduler(
|
|
|
208
211
|
"file_path",
|
|
209
212
|
type=click.File("w"),
|
|
210
213
|
)
|
|
211
|
-
|
|
212
|
-
|
|
214
|
+
@click.option(
|
|
215
|
+
"--watch",
|
|
216
|
+
is_flag=True,
|
|
217
|
+
help="Watch for file changes and regenerate TypeScript interfaces",
|
|
218
|
+
)
|
|
219
|
+
@click.option(
|
|
220
|
+
"--src-dir",
|
|
221
|
+
type=click.Path(exists=True, file_okay=False, dir_okay=True),
|
|
222
|
+
default="src",
|
|
223
|
+
help="Source directory to watch for changes (default: src)",
|
|
224
|
+
)
|
|
225
|
+
def gen_tsi(app_path: str, file_path: StreamWriter, watch: bool, src_dir: str) -> None:
|
|
226
|
+
"""Generate TypeScript interfaces from a Python microservice."""
|
|
227
|
+
|
|
228
|
+
# Generate typescript interfaces
|
|
229
|
+
def generate_interfaces() -> None:
|
|
230
|
+
try:
|
|
231
|
+
app = find_microservice_by_module_path(app_path)
|
|
232
|
+
content = write_microservice_to_typescript_interface(app)
|
|
233
|
+
|
|
234
|
+
# Save current position
|
|
235
|
+
file_path.tell()
|
|
236
|
+
|
|
237
|
+
# Reset file to beginning
|
|
238
|
+
file_path.seek(0)
|
|
239
|
+
file_path.truncate()
|
|
240
|
+
|
|
241
|
+
# Write new content
|
|
242
|
+
file_path.write(content)
|
|
243
|
+
file_path.flush()
|
|
213
244
|
|
|
214
|
-
|
|
245
|
+
print(f"Generated TypeScript interfaces at {time.strftime('%H:%M:%S')}")
|
|
246
|
+
except Exception as e:
|
|
247
|
+
print(f"Error generating TypeScript interfaces: {e}", file=sys.stderr)
|
|
215
248
|
|
|
216
|
-
|
|
249
|
+
# Initial generation
|
|
250
|
+
generate_interfaces()
|
|
251
|
+
|
|
252
|
+
# If watch mode is not enabled, exit
|
|
253
|
+
if not watch:
|
|
254
|
+
return
|
|
255
|
+
|
|
256
|
+
try:
|
|
257
|
+
from watchdog.events import FileSystemEvent, FileSystemEventHandler
|
|
258
|
+
from watchdog.observers import Observer
|
|
259
|
+
except ImportError:
|
|
260
|
+
print(
|
|
261
|
+
"Watchdog is required for watch mode. Install it with: pip install watchdog",
|
|
262
|
+
file=sys.stderr,
|
|
263
|
+
)
|
|
264
|
+
return
|
|
265
|
+
|
|
266
|
+
# Set up file system event handler
|
|
267
|
+
class PyFileChangeHandler(FileSystemEventHandler):
|
|
268
|
+
def on_modified(self, event: FileSystemEvent) -> None:
|
|
269
|
+
src_path = (
|
|
270
|
+
event.src_path
|
|
271
|
+
if isinstance(event.src_path, str)
|
|
272
|
+
else str(event.src_path)
|
|
273
|
+
)
|
|
274
|
+
if not event.is_directory and src_path.endswith(".py"):
|
|
275
|
+
print(f"File changed: {src_path}")
|
|
276
|
+
generate_interfaces()
|
|
277
|
+
|
|
278
|
+
# Set up observer
|
|
279
|
+
observer = Observer()
|
|
280
|
+
observer.schedule(PyFileChangeHandler(), src_dir, recursive=True)
|
|
281
|
+
observer.start()
|
|
282
|
+
|
|
283
|
+
print(f"Watching for changes in {os.path.abspath(src_dir)}...")
|
|
284
|
+
try:
|
|
285
|
+
while True:
|
|
286
|
+
time.sleep(1)
|
|
287
|
+
except KeyboardInterrupt:
|
|
288
|
+
observer.stop()
|
|
289
|
+
print("Watch mode stopped")
|
|
290
|
+
observer.join()
|
|
217
291
|
|
|
218
292
|
|
|
219
293
|
def camel_case_to_snake_case(name: str) -> str:
|
|
@@ -2,6 +2,7 @@ from contextlib import asynccontextmanager
|
|
|
2
2
|
from typing import Any, AsyncContextManager, AsyncGenerator, Protocol
|
|
3
3
|
|
|
4
4
|
import aio_pika
|
|
5
|
+
from aio_pika.abc import AbstractConnection
|
|
5
6
|
from pydantic import BaseModel
|
|
6
7
|
|
|
7
8
|
from jararaca.messagebus.publisher import MessagePublisher, provide_message_publisher
|
|
@@ -25,6 +26,10 @@ class MessageBusPublisherInterceptor(AppInterceptor):
|
|
|
25
26
|
|
|
26
27
|
@asynccontextmanager
|
|
27
28
|
async def intercept(self, app_context: AppContext) -> AsyncGenerator[None, None]:
|
|
29
|
+
if app_context.context_type == "websocket":
|
|
30
|
+
yield
|
|
31
|
+
return
|
|
32
|
+
|
|
28
33
|
async with self.connection_factory.provide_connection() as connection:
|
|
29
34
|
with provide_message_publisher(self.connection_name, connection):
|
|
30
35
|
yield
|
|
@@ -48,29 +53,79 @@ class AIOPikaMessagePublisher(MessagePublisher):
|
|
|
48
53
|
)
|
|
49
54
|
|
|
50
55
|
|
|
56
|
+
class GenericPoolConfig(BaseModel):
|
|
57
|
+
max_size: int
|
|
58
|
+
|
|
59
|
+
|
|
51
60
|
class AIOPikaConnectionFactory(MessageBusConnectionFactory):
|
|
52
61
|
|
|
53
62
|
def __init__(
|
|
54
63
|
self,
|
|
55
64
|
url: str,
|
|
56
65
|
exchange: str,
|
|
66
|
+
connection_pool_config: GenericPoolConfig | None = None,
|
|
67
|
+
channel_pool_config: GenericPoolConfig | None = None,
|
|
57
68
|
):
|
|
58
69
|
self.url = url
|
|
59
70
|
self.exchange = exchange
|
|
60
71
|
|
|
72
|
+
self.connection_pool: aio_pika.pool.Pool[AbstractConnection] | None = None
|
|
73
|
+
self.channel_pool: aio_pika.pool.Pool[aio_pika.abc.AbstractChannel] | None = (
|
|
74
|
+
None
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
if connection_pool_config:
|
|
78
|
+
|
|
79
|
+
async def get_connection() -> AbstractConnection:
|
|
80
|
+
return await aio_pika.connect_robust(self.url)
|
|
81
|
+
|
|
82
|
+
self.connection_pool = aio_pika.pool.Pool[AbstractConnection](
|
|
83
|
+
get_connection,
|
|
84
|
+
max_size=connection_pool_config.max_size,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
if channel_pool_config:
|
|
88
|
+
|
|
89
|
+
async def get_channel() -> aio_pika.abc.AbstractChannel:
|
|
90
|
+
async with self.acquire_connection() as connection:
|
|
91
|
+
return await connection.channel(publisher_confirms=False)
|
|
92
|
+
|
|
93
|
+
self.channel_pool = aio_pika.pool.Pool[aio_pika.abc.AbstractChannel](
|
|
94
|
+
get_channel, max_size=channel_pool_config.max_size
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
@asynccontextmanager
|
|
98
|
+
async def acquire_connection(self) -> AsyncGenerator[AbstractConnection, Any]:
|
|
99
|
+
if not self.connection_pool:
|
|
100
|
+
async with await aio_pika.connect_robust(self.url) as connection:
|
|
101
|
+
yield connection
|
|
102
|
+
else:
|
|
103
|
+
|
|
104
|
+
async with self.connection_pool.acquire() as connection:
|
|
105
|
+
yield connection
|
|
106
|
+
|
|
107
|
+
@asynccontextmanager
|
|
108
|
+
async def acquire_channel(
|
|
109
|
+
self,
|
|
110
|
+
) -> AsyncGenerator[aio_pika.abc.AbstractChannel, Any]:
|
|
111
|
+
if not self.channel_pool:
|
|
112
|
+
async with self.acquire_connection() as connection:
|
|
113
|
+
yield await connection.channel(publisher_confirms=False)
|
|
114
|
+
else:
|
|
115
|
+
async with self.channel_pool.acquire() as channel:
|
|
116
|
+
yield channel
|
|
117
|
+
|
|
61
118
|
@asynccontextmanager
|
|
62
119
|
async def provide_connection(self) -> AsyncGenerator[AIOPikaMessagePublisher, Any]:
|
|
63
|
-
connection = await aio_pika.connect_robust(self.url)
|
|
64
|
-
async with connection:
|
|
65
|
-
async with connection.channel(publisher_confirms=False) as channel:
|
|
66
120
|
|
|
67
|
-
|
|
121
|
+
async with self.acquire_channel() as channel:
|
|
122
|
+
tx = channel.transaction()
|
|
68
123
|
|
|
69
|
-
|
|
124
|
+
await tx.select()
|
|
70
125
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
126
|
+
try:
|
|
127
|
+
yield AIOPikaMessagePublisher(channel, exchange_name=self.exchange)
|
|
128
|
+
await tx.commit()
|
|
129
|
+
except Exception as e:
|
|
130
|
+
await tx.rollback()
|
|
131
|
+
raise e
|
jararaca/messagebus/worker.py
CHANGED
|
@@ -205,17 +205,17 @@ class MessageHandlerCallback:
|
|
|
205
205
|
self, aio_pika_message: aio_pika.abc.AbstractIncomingMessage
|
|
206
206
|
) -> None:
|
|
207
207
|
|
|
208
|
-
|
|
208
|
+
routing_key = self.queue_name
|
|
209
209
|
|
|
210
|
-
if
|
|
210
|
+
if routing_key is None:
|
|
211
211
|
logger.warning("No topic found for message")
|
|
212
212
|
await self.handle_reject_message(aio_pika_message)
|
|
213
213
|
return
|
|
214
214
|
|
|
215
|
-
handler_data = self.consumer.incoming_map.get(
|
|
215
|
+
handler_data = self.consumer.incoming_map.get(routing_key)
|
|
216
216
|
|
|
217
217
|
if handler_data is None:
|
|
218
|
-
logger.warning("No handler found for topic '%s'" %
|
|
218
|
+
logger.warning("No handler found for topic '%s'" % routing_key)
|
|
219
219
|
await self.handle_reject_message(aio_pika_message)
|
|
220
220
|
|
|
221
221
|
return
|
|
@@ -227,7 +227,7 @@ class MessageHandlerCallback:
|
|
|
227
227
|
if len(sig.parameters) != 1:
|
|
228
228
|
logger.warning(
|
|
229
229
|
"Handler for topic '%s' must have exactly one parameter which is MessageOf[T extends Message]"
|
|
230
|
-
%
|
|
230
|
+
% routing_key
|
|
231
231
|
)
|
|
232
232
|
return
|
|
233
233
|
|
|
@@ -238,14 +238,14 @@ class MessageHandlerCallback:
|
|
|
238
238
|
if param_origin is not MessageOf:
|
|
239
239
|
logger.warning(
|
|
240
240
|
"Handler for topic '%s' must have exactly one parameter of type Message"
|
|
241
|
-
%
|
|
241
|
+
% routing_key
|
|
242
242
|
)
|
|
243
243
|
return
|
|
244
244
|
|
|
245
245
|
if len(parameter.annotation.__args__) != 1:
|
|
246
246
|
logger.warning(
|
|
247
247
|
"Handler for topic '%s' must have exactly one parameter of type Message"
|
|
248
|
-
%
|
|
248
|
+
% routing_key
|
|
249
249
|
)
|
|
250
250
|
return
|
|
251
251
|
|
|
@@ -253,8 +253,8 @@ class MessageHandlerCallback:
|
|
|
253
253
|
|
|
254
254
|
if not issubclass(message_type, BaseModel):
|
|
255
255
|
logger.warning(
|
|
256
|
-
"Handler for topic '%s' must have exactly one parameter of type
|
|
257
|
-
%
|
|
256
|
+
"Handler for topic '%s' must have exactly one parameter of type MessageOf[BaseModel]"
|
|
257
|
+
% routing_key
|
|
258
258
|
)
|
|
259
259
|
return
|
|
260
260
|
|
|
@@ -266,7 +266,7 @@ class MessageHandlerCallback:
|
|
|
266
266
|
async with self.consumer.uow_context_provider(
|
|
267
267
|
MessageBusAppContext(
|
|
268
268
|
message=builded_message,
|
|
269
|
-
topic=
|
|
269
|
+
topic=routing_key,
|
|
270
270
|
)
|
|
271
271
|
):
|
|
272
272
|
ctx: AsyncContextManager[Any]
|
|
@@ -293,7 +293,7 @@ class MessageHandlerCallback:
|
|
|
293
293
|
)
|
|
294
294
|
else:
|
|
295
295
|
logger.exception(
|
|
296
|
-
f"Error processing message on topic {
|
|
296
|
+
f"Error processing message on topic {routing_key}"
|
|
297
297
|
)
|
|
298
298
|
if incoming_message_spec.requeue_on_exception:
|
|
299
299
|
await self.handle_reject_message(aio_pika_message, requeue=True)
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: jararaca
|
|
3
|
+
Version: 0.2.37a12
|
|
4
|
+
Summary: A simple and fast API framework for Python
|
|
5
|
+
Author: Lucas S
|
|
6
|
+
Author-email: me@luscasleo.dev
|
|
7
|
+
Requires-Python: >=3.11,<4.0
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Provides-Extra: docs
|
|
13
|
+
Provides-Extra: http
|
|
14
|
+
Provides-Extra: opentelemetry
|
|
15
|
+
Requires-Dist: aio-pika (>=9.4.3,<10.0.0)
|
|
16
|
+
Requires-Dist: croniter (>=3.0.3,<4.0.0)
|
|
17
|
+
Requires-Dist: fastapi (>=0.113.0,<0.114.0)
|
|
18
|
+
Requires-Dist: mako (>=1.3.5,<2.0.0)
|
|
19
|
+
Requires-Dist: opentelemetry-api (>=1.27.0,<2.0.0) ; extra == "opentelemetry"
|
|
20
|
+
Requires-Dist: opentelemetry-distro (>=0.49b2,<0.50) ; extra == "opentelemetry"
|
|
21
|
+
Requires-Dist: opentelemetry-exporter-otlp (>=1.27.0,<2.0.0) ; extra == "opentelemetry"
|
|
22
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http (>=1.27.0,<2.0.0) ; extra == "opentelemetry"
|
|
23
|
+
Requires-Dist: opentelemetry-sdk (>=1.27.0,<2.0.0) ; extra == "opentelemetry"
|
|
24
|
+
Requires-Dist: redis (>=5.0.8,<6.0.0)
|
|
25
|
+
Requires-Dist: sqlalchemy (>=2.0.34,<3.0.0)
|
|
26
|
+
Requires-Dist: types-croniter (>=3.0.3.20240731,<4.0.0.0)
|
|
27
|
+
Requires-Dist: types-redis (>=4.6.0.20240903,<5.0.0.0)
|
|
28
|
+
Requires-Dist: uvicorn (>=0.30.6,<0.31.0)
|
|
29
|
+
Requires-Dist: uvloop (>=0.20.0,<0.21.0)
|
|
30
|
+
Requires-Dist: websockets (>=13.0.1,<14.0.0)
|
|
31
|
+
Project-URL: Repository, https://github.com/LuscasLeo/jararaca
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
<img src="https://raw.githubusercontent.com/LuscasLeo/jararaca/main/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.jpeg" alt="Jararaca Logo" width="250" float="right">
|
|
35
|
+
|
|
36
|
+
# Jararaca Microservice Framework
|
|
37
|
+
|
|
38
|
+
## Overview
|
|
39
|
+
|
|
40
|
+
Jararaca is an async-first microservice framework designed to simplify the development of distributed systems. It provides a comprehensive set of tools for building robust, scalable, and maintainable microservices with a focus on developer experience and type safety.
|
|
41
|
+
|
|
42
|
+
## Key Features
|
|
43
|
+
|
|
44
|
+
### REST API Development
|
|
45
|
+
- Easy-to-use interfaces for building REST APIs
|
|
46
|
+
- Automatic request/response validation
|
|
47
|
+
- Type-safe endpoints with FastAPI integration
|
|
48
|
+
- Automatic OpenAPI documentation generation
|
|
49
|
+
|
|
50
|
+
### Message Bus Integration
|
|
51
|
+
- Topic-based message bus for event-driven architecture
|
|
52
|
+
- Support for both worker and publisher patterns
|
|
53
|
+
- Built-in message serialization and deserialization
|
|
54
|
+
- Easy integration with AIO Pika for RabbitMQ
|
|
55
|
+
|
|
56
|
+
### Distributed WebSocket
|
|
57
|
+
- Room-based WebSocket communication
|
|
58
|
+
- Distributed broadcasting across multiple backend instances
|
|
59
|
+
- Automatic message synchronization between instances
|
|
60
|
+
- Built-in connection management and room handling
|
|
61
|
+
|
|
62
|
+
### Task Scheduling
|
|
63
|
+
- Cron-based task scheduling
|
|
64
|
+
- Support for overlapping and non-overlapping tasks
|
|
65
|
+
- Distributed task execution
|
|
66
|
+
- Easy integration with message bus for task distribution
|
|
67
|
+
|
|
68
|
+
### TypeScript Integration
|
|
69
|
+
- Automatic TypeScript interface generation
|
|
70
|
+
- Command-line tool for generating TypeScript types
|
|
71
|
+
- Support for REST endpoints, WebSocket events, and message bus payloads
|
|
72
|
+
- Type-safe frontend-backend communication
|
|
73
|
+
|
|
74
|
+
### Hexagonal Architecture
|
|
75
|
+
- Clear separation of concerns
|
|
76
|
+
- Business logic isolation from infrastructure
|
|
77
|
+
- Easy testing and maintainability
|
|
78
|
+
- Dependency injection for flexible component management
|
|
79
|
+
|
|
80
|
+
### Observability
|
|
81
|
+
- Built-in OpenTelemetry integration
|
|
82
|
+
- Distributed tracing support
|
|
83
|
+
- Logging and metrics collection
|
|
84
|
+
- Performance monitoring capabilities
|
|
85
|
+
|
|
86
|
+
## Quick Start
|
|
87
|
+
|
|
88
|
+
### Installation
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
pip install jararaca
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Basic Usage
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from jararaca import Microservice, create_http_server
|
|
98
|
+
from jararaca.presentation.http_microservice import HttpMicroservice
|
|
99
|
+
|
|
100
|
+
# Define your microservice
|
|
101
|
+
app = Microservice(
|
|
102
|
+
providers=[
|
|
103
|
+
# Add your providers here
|
|
104
|
+
],
|
|
105
|
+
controllers=[
|
|
106
|
+
# Add your controllers here
|
|
107
|
+
],
|
|
108
|
+
interceptors=[
|
|
109
|
+
# Add your interceptors here
|
|
110
|
+
],
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Create HTTP server
|
|
114
|
+
http_app = HttpMicroservice(app)
|
|
115
|
+
web_app = create_http_server(app)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Running the Service
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# Run as HTTP server
|
|
122
|
+
jararaca server app:http_app
|
|
123
|
+
|
|
124
|
+
# Run as message bus worker
|
|
125
|
+
jararaca worker app:app
|
|
126
|
+
|
|
127
|
+
# Run as scheduler
|
|
128
|
+
jararaca scheduler app:app
|
|
129
|
+
|
|
130
|
+
# Generate TypeScript interfaces
|
|
131
|
+
jararaca gen-tsi app.main:app app.ts
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Documentation
|
|
135
|
+
|
|
136
|
+
For detailed documentation, please visit our [documentation site](https://luscasleo.github.io/jararaca/).
|
|
137
|
+
|
|
138
|
+
## Examples
|
|
139
|
+
|
|
140
|
+
Check out the [examples directory](examples/) for complete working examples of:
|
|
141
|
+
- REST API implementation
|
|
142
|
+
- WebSocket usage
|
|
143
|
+
- Message bus integration
|
|
144
|
+
- Task scheduling
|
|
145
|
+
- TypeScript interface generation
|
|
146
|
+
|
|
147
|
+
## Contributing
|
|
148
|
+
|
|
149
|
+
Contributions are welcome! Please read our [contributing guidelines](.github/CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
|
|
150
|
+
|
|
151
|
+
## License
|
|
152
|
+
|
|
153
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
154
|
+
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
README.md,sha256=mte30I-ZEJJp-Oax-OganNgl6G9GaCZPL6JVFAvZGz4,7034
|
|
3
|
-
pyproject.toml,sha256=Hz6Rk-E8INfd6U7oblRlcW8Qvm_aRmyY_EjWaGj6ukw,1840
|
|
4
|
-
jararaca/__init__.py,sha256=gDCvrIhIu5_IkKjmZmhWZ2khOi8WGiw2AidFFe-BnWU,15118
|
|
1
|
+
jararaca/__init__.py,sha256=VBrN25GHJ3gDG95CcJWe3dmGcA-X2agzOCIBbjzc1Iw,15312
|
|
5
2
|
jararaca/__main__.py,sha256=-O3vsB5lHdqNFjUtoELDF81IYFtR-DSiiFMzRaiSsv4,67
|
|
6
|
-
jararaca/cli.py,sha256=
|
|
3
|
+
jararaca/cli.py,sha256=K6df8fqEc4Qj-yGz5hmO3pSgFWxcLP4iciOP4LHida4,7979
|
|
7
4
|
jararaca/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
5
|
jararaca/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
6
|
jararaca/core/providers.py,sha256=wktH84FK7c1s2wNq-fudf1uMfi3CQBR0neU2czJ_L0U,434
|
|
@@ -15,10 +12,10 @@ jararaca/messagebus/__init__.py,sha256=Zdl74HcS9K0FW6XUt7bVvaHEyxL8pWsqqakeRENIn
|
|
|
15
12
|
jararaca/messagebus/bus_message_controller.py,sha256=Xd_qwnX5jUvgBTCarHR36fvtol9lPTsYp2IIGKyQQaE,1487
|
|
16
13
|
jararaca/messagebus/decorators.py,sha256=GHlaXRuHtrz6R0HgcG2gJybpGYtdts9meDVSRPwN74I,4245
|
|
17
14
|
jararaca/messagebus/interceptors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
-
jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py,sha256=
|
|
15
|
+
jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py,sha256=BPH5wOlj_CyHtJ7W4NWF2h0gYMwzOPNzFhGADk618N4,4373
|
|
19
16
|
jararaca/messagebus/publisher.py,sha256=5ay9Znwybqt981OOykdWkFisSvGiTeTpPXDFLMnaiqg,1109
|
|
20
17
|
jararaca/messagebus/types.py,sha256=iYLyLxWqOHkDadxyMqQPWy3itLNQfvD6oQe8jcq9nzo,887
|
|
21
|
-
jararaca/messagebus/worker.py,sha256=
|
|
18
|
+
jararaca/messagebus/worker.py,sha256=_X2Ctj7bI9XjCMvQMy8jM3dEE3CGnqgrU_B3lTGfmmQ,13605
|
|
22
19
|
jararaca/microservice.py,sha256=1TvDKVMMREH27Ly8eTEheMmSfro4_Az_JKM_NdDvrgc,6636
|
|
23
20
|
jararaca/observability/decorators.py,sha256=XffBinFXdiNkY6eo8_1nkr_GapM0RUGBg0aicBIelag,2220
|
|
24
21
|
jararaca/observability/interceptor.py,sha256=GHkuGKFWftN7MDjvYeGFGEPnuJETNhtxRK6yuPrCrpU,1462
|
|
@@ -59,8 +56,8 @@ jararaca/tools/app_config/decorators.py,sha256=-ckkMZ1dswOmECdo1rFrZ15UAku--txaN
|
|
|
59
56
|
jararaca/tools/app_config/interceptor.py,sha256=nfFZiS80hrbnL7-XEYrwmp2rwaVYBqxvqu3Y-6o_ov4,2575
|
|
60
57
|
jararaca/tools/metadata.py,sha256=7nlCDYgItNybentPSSCc2MLqN7IpBd0VyQzfjfQycVI,1402
|
|
61
58
|
jararaca/tools/typescript/interface_parser.py,sha256=4SHt094P-QawMFHSyMCiujQf8Niw7xACIO1RHBM8-w4,29192
|
|
62
|
-
jararaca-0.2.
|
|
63
|
-
jararaca-0.2.
|
|
64
|
-
jararaca-0.2.
|
|
65
|
-
jararaca-0.2.
|
|
66
|
-
jararaca-0.2.
|
|
59
|
+
jararaca-0.2.37a12.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
60
|
+
jararaca-0.2.37a12.dist-info/METADATA,sha256=W8aHUpqo5Q5iGBwX0BE4CS9MfEEMN97vM-YRuCJ2URM,4873
|
|
61
|
+
jararaca-0.2.37a12.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
|
62
|
+
jararaca-0.2.37a12.dist-info/entry_points.txt,sha256=WIh3aIvz8LwUJZIDfs4EeH3VoFyCGEk7cWJurW38q0I,45
|
|
63
|
+
jararaca-0.2.37a12.dist-info/RECORD,,
|