modmex-lambda 0.1.0__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.
- modmex_lambda/__init__.py +62 -0
- modmex_lambda/data_classes/__init__.py +49 -0
- modmex_lambda/data_classes/api_gateway_authorizer_event.py +38 -0
- modmex_lambda/data_classes/api_gateway_proxy_event.py +328 -0
- modmex_lambda/data_classes/api_gateway_websocket_event.py +40 -0
- modmex_lambda/data_classes/cognito_user_pool_event.py +599 -0
- modmex_lambda/data_classes/common.py +441 -0
- modmex_lambda/event_handler/__init__.py +45 -0
- modmex_lambda/event_handler/api_gateway.py +331 -0
- modmex_lambda/event_handler/constants.py +3 -0
- modmex_lambda/event_handler/content_types.py +13 -0
- modmex_lambda/event_handler/cors.py +97 -0
- modmex_lambda/event_handler/dependencies/__init__.py +0 -0
- modmex_lambda/event_handler/dependencies/compat.py +231 -0
- modmex_lambda/event_handler/dependencies/dependant.py +279 -0
- modmex_lambda/event_handler/dependencies/dependency_middleware.py +423 -0
- modmex_lambda/event_handler/dependencies/depends.py +184 -0
- modmex_lambda/event_handler/dependencies/params.py +317 -0
- modmex_lambda/event_handler/dependencies/types.py +14 -0
- modmex_lambda/event_handler/exception_handler.py +70 -0
- modmex_lambda/event_handler/exceptions.py +72 -0
- modmex_lambda/event_handler/gateway_response.py +96 -0
- modmex_lambda/event_handler/middlewares.py +33 -0
- modmex_lambda/event_handler/params.py +44 -0
- modmex_lambda/event_handler/request.py +70 -0
- modmex_lambda/event_handler/response.py +60 -0
- modmex_lambda/event_handler/routing.py +507 -0
- modmex_lambda/event_handler/routing_fallbacks.py +92 -0
- modmex_lambda/event_handler/types.py +31 -0
- modmex_lambda/event_sources.py +53 -0
- modmex_lambda/exceptions.py +3 -0
- modmex_lambda/logging.py +99 -0
- modmex_lambda/params.py +3 -0
- modmex_lambda/parser.py +47 -0
- modmex_lambda/request.py +3 -0
- modmex_lambda/resolver.py +3 -0
- modmex_lambda/response.py +3 -0
- modmex_lambda/routing.py +3 -0
- modmex_lambda/shared/__init__.py +0 -0
- modmex_lambda/shared/cookies.py +84 -0
- modmex_lambda/shared/headers_serializer.py +65 -0
- modmex_lambda/shared/json_encoder.py +53 -0
- modmex_lambda/shared/types.py +4 -0
- modmex_lambda/validation.py +178 -0
- modmex_lambda-0.1.0.dist-info/METADATA +375 -0
- modmex_lambda-0.1.0.dist-info/RECORD +48 -0
- modmex_lambda-0.1.0.dist-info/WHEEL +4 -0
- modmex_lambda-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: modmex-lambda
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Ultra-lightweight AWS Lambda utilities for API Gateway routing and event handling.
|
|
5
|
+
Author: Modmex
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Requires-Dist: modmex<2.0.0,>=1.1.10
|
|
10
|
+
Provides-Extra: dev
|
|
11
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# modmex-lambda
|
|
15
|
+
|
|
16
|
+
Ultra-lightweight AWS Lambda utilities for API Gateway-first workloads.
|
|
17
|
+
|
|
18
|
+
`modmex-lambda` is a Lambda utility layer, not an ASGI framework. It focuses on
|
|
19
|
+
API Gateway proxy events, fast routing, request binding, response serialization,
|
|
20
|
+
middleware, dependency injection, event source wrappers, parsing, and structured
|
|
21
|
+
logging with a small dependency footprint.
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install modmex-lambda
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
For local development:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
poetry install --extras dev
|
|
33
|
+
poetry run pytest -q
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## API Gateway Resolvers
|
|
37
|
+
|
|
38
|
+
Choose the resolver that matches the API Gateway payload version used by your
|
|
39
|
+
Lambda integration:
|
|
40
|
+
|
|
41
|
+
- `ApiGatewayRestResolver` for REST API payload v1.
|
|
42
|
+
- `ApiGatewayHttpResolver` for HTTP API payload v2 and Lambda Function URLs.
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from modmex_lambda import ApiGatewayHttpResolver
|
|
46
|
+
|
|
47
|
+
app = ApiGatewayHttpResolver()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@app.get("/ping")
|
|
51
|
+
def ping():
|
|
52
|
+
return {"message": "pong"}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
handler = app.handler
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The internal base resolver is intentionally not exported from the package root;
|
|
59
|
+
application code should select REST or HTTP explicitly.
|
|
60
|
+
|
|
61
|
+
## Routing
|
|
62
|
+
|
|
63
|
+
Routes are declared with decorators:
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
@app.get("/users/<user_id>")
|
|
67
|
+
def get_user(user_id: int):
|
|
68
|
+
return {"user_id": user_id}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@app.post("/users", status_code=201)
|
|
72
|
+
def create_user():
|
|
73
|
+
return {"id": 42}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Supported route decorators include `get`, `post`, `put`, `patch`, `delete`,
|
|
77
|
+
`options`, and `any`.
|
|
78
|
+
|
|
79
|
+
Routers can also strip deployment prefixes:
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
app = ApiGatewayHttpResolver(strip_prefixes=["/prod"])
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Request Binding
|
|
86
|
+
|
|
87
|
+
Use `typing.Annotated` with the public parameter markers:
|
|
88
|
+
|
|
89
|
+
- `Path()`
|
|
90
|
+
- `Query()`
|
|
91
|
+
- `Header()`
|
|
92
|
+
- `Cookie()`
|
|
93
|
+
- `Body()`
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from typing import Annotated
|
|
97
|
+
|
|
98
|
+
from modmex import BaseModel
|
|
99
|
+
from modmex_lambda import ApiGatewayHttpResolver, Request
|
|
100
|
+
from modmex_lambda.event_handler.params import Body, Header, Path, Query
|
|
101
|
+
|
|
102
|
+
app = ApiGatewayHttpResolver()
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class CreateUserRequest(BaseModel):
|
|
106
|
+
name: str
|
|
107
|
+
age: int | None = None
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@app.post("/users", status_code=201)
|
|
111
|
+
def create_user(
|
|
112
|
+
payload: Annotated[CreateUserRequest, Body()],
|
|
113
|
+
tenant_id: Annotated[str, Header(name="x-tenant-id")],
|
|
114
|
+
request: Request,
|
|
115
|
+
):
|
|
116
|
+
return {
|
|
117
|
+
"id": 42,
|
|
118
|
+
"tenant_id": tenant_id,
|
|
119
|
+
"route": request.route,
|
|
120
|
+
"payload": payload.model_dump(),
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@app.get("/users/<user_id>")
|
|
125
|
+
def get_user(
|
|
126
|
+
user_id: Annotated[int, Path()],
|
|
127
|
+
include_orders: Annotated[bool, Query()] = False,
|
|
128
|
+
):
|
|
129
|
+
return {"user_id": user_id, "include_orders": include_orders}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
For headers, simple scalar parameters can use `Header(name="x-header-name")`.
|
|
133
|
+
Header models are also supported; field names are exposed as dash-case aliases.
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
class HeaderModel(BaseModel):
|
|
137
|
+
x_tenant_id: str
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
@app.get("/me")
|
|
141
|
+
def me(headers: Annotated[HeaderModel, Header()]):
|
|
142
|
+
return {"tenant": headers.x_tenant_id}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Responses
|
|
146
|
+
|
|
147
|
+
Route return values are converted to API Gateway proxy responses:
|
|
148
|
+
|
|
149
|
+
- `dict` and `list` become JSON responses.
|
|
150
|
+
- `str` becomes a text response.
|
|
151
|
+
- `bytes` are base64 encoded.
|
|
152
|
+
- `None` returns an empty response.
|
|
153
|
+
- `(body, status_code)` sets the response status.
|
|
154
|
+
- `Response` gives full control over status, headers, cookies, and content type.
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
from modmex_lambda import Response
|
|
158
|
+
from modmex_lambda.shared.cookies import Cookie
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@app.get("/session")
|
|
162
|
+
def session():
|
|
163
|
+
return Response(
|
|
164
|
+
status_code=200,
|
|
165
|
+
body={"ok": True},
|
|
166
|
+
cookies=[Cookie("seen", "true", secure=True)],
|
|
167
|
+
)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
REST API responses use `multiValueHeaders`; HTTP API responses use the v2
|
|
171
|
+
`headers` and `cookies` shape.
|
|
172
|
+
|
|
173
|
+
## Middleware
|
|
174
|
+
|
|
175
|
+
Middleware receives the resolver instance and a `next_middleware` callable.
|
|
176
|
+
Global middleware can be registered with `use` or `@app.middleware`; route
|
|
177
|
+
middleware can be attached per route.
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
from modmex_lambda import Response
|
|
181
|
+
from modmex_lambda.event_handler.middlewares import NextMiddleware
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
@app.middleware
|
|
185
|
+
def require_auth(app: ApiGatewayHttpResolver, next_middleware: NextMiddleware) -> Response:
|
|
186
|
+
if app.current_event.headers.get("x-auth") != "ok":
|
|
187
|
+
return Response(status_code=401, body={"message": "Unauthorized"})
|
|
188
|
+
return next_middleware(app)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Middleware also wraps routing fallbacks, so `404` and `405` responses still flow
|
|
192
|
+
through the middleware chain.
|
|
193
|
+
|
|
194
|
+
## Dependency Injection
|
|
195
|
+
|
|
196
|
+
`Depends` supports nested dependency trees, request-aware dependencies,
|
|
197
|
+
per-invocation caching, and overrides for tests.
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
from typing import Annotated
|
|
201
|
+
|
|
202
|
+
from modmex_lambda import Depends, Request
|
|
203
|
+
from modmex_lambda.event_handler.params import Path
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
class UserRepository:
|
|
207
|
+
def __init__(self, *, tenant_id: str, token: str):
|
|
208
|
+
self.tenant_id = tenant_id
|
|
209
|
+
self.token = token
|
|
210
|
+
|
|
211
|
+
def get_user(self, user_id: int) -> dict:
|
|
212
|
+
# Replace this with a database or service call.
|
|
213
|
+
return {"id": user_id, "tenant_id": self.tenant_id}
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def get_token() -> str:
|
|
217
|
+
return "token"
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def get_tenant_id(request: Request) -> str:
|
|
221
|
+
return request.headers["x-tenant-id"]
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def get_user_repository(
|
|
225
|
+
tenant_id: Annotated[str, Depends(get_tenant_id)],
|
|
226
|
+
token: Annotated[str, Depends(get_token)],
|
|
227
|
+
) -> UserRepository:
|
|
228
|
+
return UserRepository(tenant_id=tenant_id, token=token)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
@app.get("/users/<user_id>")
|
|
232
|
+
def get_user(
|
|
233
|
+
user_id: Annotated[int, Path()],
|
|
234
|
+
repository: Annotated[UserRepository, Depends(get_user_repository)],
|
|
235
|
+
):
|
|
236
|
+
return repository.get_user(user_id)
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Disable dependency caching when a dependency must run every time:
|
|
240
|
+
|
|
241
|
+
```python
|
|
242
|
+
def next_counter() -> int:
|
|
243
|
+
...
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
@app.get("/counter")
|
|
247
|
+
def counter(value: Annotated[int, Depends(next_counter, use_cache=False)]):
|
|
248
|
+
return {"value": value}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
For tests, set `app.dependency_overrides`:
|
|
252
|
+
|
|
253
|
+
```python
|
|
254
|
+
app.dependency_overrides[get_token] = lambda: "test-token"
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Exception Handling
|
|
258
|
+
|
|
259
|
+
Built-in error responses:
|
|
260
|
+
|
|
261
|
+
- request validation errors return `400`.
|
|
262
|
+
- `NotFoundError` returns `404`.
|
|
263
|
+
- `MethodNotAllowedError` returns `405`.
|
|
264
|
+
- `UnauthorizedError` returns `401`.
|
|
265
|
+
- `ForbiddenError` returns `403`.
|
|
266
|
+
|
|
267
|
+
Custom handlers can be registered per exception type. The most specific handler
|
|
268
|
+
wins.
|
|
269
|
+
|
|
270
|
+
```python
|
|
271
|
+
from modmex_lambda import Response
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
class DomainError(Exception):
|
|
275
|
+
pass
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
@app.exception_handler(DomainError)
|
|
279
|
+
def on_domain_error(exc: DomainError):
|
|
280
|
+
return Response(status_code=409, body={"message": str(exc)})
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
If a custom exception handler raises, the resolver falls back to the default
|
|
284
|
+
error response when one exists.
|
|
285
|
+
|
|
286
|
+
## CORS
|
|
287
|
+
|
|
288
|
+
Pass `CORSConfig` to the resolver to add CORS headers and automatic preflight
|
|
289
|
+
behavior.
|
|
290
|
+
|
|
291
|
+
```python
|
|
292
|
+
from modmex_lambda import ApiGatewayHttpResolver
|
|
293
|
+
from modmex_lambda.event_handler.cors import CORSConfig
|
|
294
|
+
|
|
295
|
+
app = ApiGatewayHttpResolver(
|
|
296
|
+
cors=CORSConfig(
|
|
297
|
+
allow_origin="https://app.example",
|
|
298
|
+
allow_headers=["X-Tenant-Id"],
|
|
299
|
+
allow_credentials=True,
|
|
300
|
+
),
|
|
301
|
+
)
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Parser
|
|
305
|
+
|
|
306
|
+
```python
|
|
307
|
+
from modmex_lambda.parser import event_parser, parse
|
|
308
|
+
|
|
309
|
+
parsed = parse(event={"name": "Ada"}, model=MyModel)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
@event_parser(model=MyModel)
|
|
313
|
+
def lambda_handler(event: MyModel, context):
|
|
314
|
+
...
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## Event Source Data Classes
|
|
318
|
+
|
|
319
|
+
Current scoped data classes include:
|
|
320
|
+
|
|
321
|
+
- `APIGatewayProxyEvent` and `APIGatewayProxyEventV2`
|
|
322
|
+
- `APIGatewayRestEvent` and `APIGatewayHttpEvent` aliases
|
|
323
|
+
- `APIGatewayAuthorizerEvent`
|
|
324
|
+
- `APIGatewayWebSocketEvent`
|
|
325
|
+
- Cognito User Pool trigger wrappers
|
|
326
|
+
|
|
327
|
+
```python
|
|
328
|
+
from modmex_lambda.data_classes import APIGatewayHttpEvent
|
|
329
|
+
from modmex_lambda.event_sources import event_source
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
@event_source(data_class=APIGatewayHttpEvent)
|
|
333
|
+
def lambda_handler(event: APIGatewayHttpEvent, context):
|
|
334
|
+
return {"path": event.path}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## Validation
|
|
338
|
+
|
|
339
|
+
Modmex is the default validation and coercion engine. Pydantic is not required
|
|
340
|
+
for normal operation.
|
|
341
|
+
|
|
342
|
+
## Logging
|
|
343
|
+
|
|
344
|
+
```python
|
|
345
|
+
from modmex_lambda import Logger
|
|
346
|
+
|
|
347
|
+
logger = Logger(service="users")
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def lambda_handler(event, context):
|
|
351
|
+
logger.append_keys(tenant_id="mx")
|
|
352
|
+
logger.info("request received")
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
The logger emits structured JSON and can extract Lambda request IDs and API
|
|
356
|
+
Gateway correlation IDs.
|
|
357
|
+
|
|
358
|
+
## Benchmarks
|
|
359
|
+
|
|
360
|
+
The benchmark suite lives in `.benchmark/api_gateway_benchmark.py`.
|
|
361
|
+
|
|
362
|
+
It covers cold imports, app setup, route registration, API Gateway v1/v2
|
|
363
|
+
invocation, `event_parser`, `event_source`, and logger hot paths.
|
|
364
|
+
|
|
365
|
+
```bash
|
|
366
|
+
poetry run python .benchmark/api_gateway_benchmark.py
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
More details are in `.benchmark/README.md`.
|
|
370
|
+
|
|
371
|
+
## Limitations
|
|
372
|
+
|
|
373
|
+
- Event source scope is intentionally focused on API Gateway and Cognito.
|
|
374
|
+
- OpenAPI/Swagger generation is not implemented.
|
|
375
|
+
- Async resolver pipelines are not implemented yet.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
modmex_lambda/__init__.py,sha256=3gWLZwuPGrvvjTsycbsvGd4Noh4bEj87MwP32IyNrjU,1966
|
|
2
|
+
modmex_lambda/event_sources.py,sha256=eLTEN1g9JF2Nk09fMcJn43dBz8BKwCOrtxmZkzr99sM,1714
|
|
3
|
+
modmex_lambda/exceptions.py,sha256=GL6ZZKhXr0BqfCsGwzookBrUJ1M7JIU2Ju3vWdyna_s,128
|
|
4
|
+
modmex_lambda/logging.py,sha256=FFINAvMu25d0Ieow-Wa8fEjr9xvtRtPgtLixsDGFPHc,3335
|
|
5
|
+
modmex_lambda/params.py,sha256=s7cnrW2NSCwWyQ_odn0b_uQJJn_aDR0JO6XUAFKI3PY,131
|
|
6
|
+
modmex_lambda/parser.py,sha256=BO2PG1YHZsRbHxqcd4rKehJDkBoipAQjAgXi-E7mysM,1544
|
|
7
|
+
modmex_lambda/request.py,sha256=2LgG5bKFhFL8xNGaGJTK_djX0nSQOwCmjuPN54ORdL8,129
|
|
8
|
+
modmex_lambda/resolver.py,sha256=6EvyxbcrTqNy-xb8l-Pz8z3gXeuYWyQErZVyY5w--8o,126
|
|
9
|
+
modmex_lambda/response.py,sha256=n7ZjcV13IR_ohtxEs8O6T6xVhNFs0DiLlUej8PpO0no,132
|
|
10
|
+
modmex_lambda/routing.py,sha256=nCIo7UoOn9W6oZXYjjw5GxMp80jZ6nbuh4WEN6f5dSg,132
|
|
11
|
+
modmex_lambda/validation.py,sha256=64uWzSnkxzN1t7DAqC_0TYzhupQUtAWnrLATEFAEfzs,7130
|
|
12
|
+
modmex_lambda/data_classes/__init__.py,sha256=puf_FWi1HaqzoPw2mhA-gUUJB_8v6x1ndp0dgoGRDp0,1711
|
|
13
|
+
modmex_lambda/data_classes/api_gateway_authorizer_event.py,sha256=Qk7RLWm_L67VwWbu8VRmJTUlDcAJDlFvVp-cCKm2QhA,1037
|
|
14
|
+
modmex_lambda/data_classes/api_gateway_proxy_event.py,sha256=fetGgKG4QFpPXu0lImtei29G1bgNF5hNZOdFdW8zP90,10957
|
|
15
|
+
modmex_lambda/data_classes/api_gateway_websocket_event.py,sha256=EGFqQ4SrC-ssb509UzfNLWpPm7gdtleoYz5Pvb2fIwU,1031
|
|
16
|
+
modmex_lambda/data_classes/cognito_user_pool_event.py,sha256=DwHa9xtqpFYnFKdUi1Y9RRgxvkVGJQXhFkRh7_4iAf4,18582
|
|
17
|
+
modmex_lambda/data_classes/common.py,sha256=8saOnaCxH25G-jQumUJMg6CuOhuJ6ugw4vAWH-Fn4Ls,13656
|
|
18
|
+
modmex_lambda/event_handler/__init__.py,sha256=4uB7HhYgShpgXJECQhvxJId8Y1Cbkz69M0rpuSxN0I8,1327
|
|
19
|
+
modmex_lambda/event_handler/api_gateway.py,sha256=YdgeyObhdPsBApQxnSQd-JykqJ6WKsrIqgKw5r9X8d0,11795
|
|
20
|
+
modmex_lambda/event_handler/constants.py,sha256=x53p_BZw2lmISpkO5v6d1nfuP-De9uUsUtwgJLaBHKw,28
|
|
21
|
+
modmex_lambda/event_handler/content_types.py,sha256=FcnCaAVhEOewQXAbkStMBNC63NFMxqwmEFnXcGholug,282
|
|
22
|
+
modmex_lambda/event_handler/cors.py,sha256=j8H81NdPxqRl5ikW8Wdf7o6pEIx7dGkAsCtSysYI1nc,3516
|
|
23
|
+
modmex_lambda/event_handler/exception_handler.py,sha256=zJmM_kUwq3vnzx3ETlgPs2JokQbauweuUJrCDYsPZwg,2491
|
|
24
|
+
modmex_lambda/event_handler/exceptions.py,sha256=wPova4geWuyuFsP43xyy0MIxOvDwVx-CfgwnF0QcZbk,2025
|
|
25
|
+
modmex_lambda/event_handler/gateway_response.py,sha256=9V5d8Ar7JfrsFRWk02GKzJN8maSIHdl4fLlAlgmzJSQ,3728
|
|
26
|
+
modmex_lambda/event_handler/middlewares.py,sha256=oOsQ0nOl7lc_N-kt8wTx7qOXNE5VtRjDEVdcsnYb-Sk,925
|
|
27
|
+
modmex_lambda/event_handler/params.py,sha256=nNhLKduyeQ6TI9Zli32_XtRM93e973igOOZSY0vcpy4,544
|
|
28
|
+
modmex_lambda/event_handler/request.py,sha256=f5TMv6muYfYOsLbZMPdd6kRMza8U2-UiyNmvuB5grH4,1705
|
|
29
|
+
modmex_lambda/event_handler/response.py,sha256=izW9v_0E91UsQKX6-W26wnuAy-YP2_kTPbA5OW9L3tM,1988
|
|
30
|
+
modmex_lambda/event_handler/routing.py,sha256=ofRSEfWxxAayThjgsBzZ6ZQaSFwtFxnpp1LDp-za2vY,16077
|
|
31
|
+
modmex_lambda/event_handler/routing_fallbacks.py,sha256=vx23xyg4vEKCqGg1bxBP0OxRsN8NbMkAdehfcNiqwjw,3669
|
|
32
|
+
modmex_lambda/event_handler/types.py,sha256=VKl50yStngGK1vBsPVDLQnO8zffgqL9T1StPIVY82qo,1060
|
|
33
|
+
modmex_lambda/event_handler/dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
34
|
+
modmex_lambda/event_handler/dependencies/compat.py,sha256=MPEJ9EKNja_ys4XLGIm8vTgN7Z96nmuqYHTvixHFR9A,7599
|
|
35
|
+
modmex_lambda/event_handler/dependencies/dependant.py,sha256=LWo2r6BZkOKo26tXr5g9vJ_C9Yrixf6iiFsAfM66JXw,9306
|
|
36
|
+
modmex_lambda/event_handler/dependencies/dependency_middleware.py,sha256=c_N7UgtbAVYC6xbfn_MaW7zYQxi5pSSdTeIRaz703Ak,14999
|
|
37
|
+
modmex_lambda/event_handler/dependencies/depends.py,sha256=X174dJZ_m6kYvcUvy2IJ7UuLRDV8lH2Jgiht5PQRt8w,5932
|
|
38
|
+
modmex_lambda/event_handler/dependencies/params.py,sha256=bc208GHiXCfm1V-GLeIMm8-ypZ8P8Q9qUKQkK2Vh1Fg,10085
|
|
39
|
+
modmex_lambda/event_handler/dependencies/types.py,sha256=5VA8zl-EjQDNKXOrNT7sRv_vNs40Lz8aMP-sf-lf8sk,376
|
|
40
|
+
modmex_lambda/shared/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
41
|
+
modmex_lambda/shared/cookies.py,sha256=E2hTuht5_Xljw9zOQLW6vjsOWEpQSIqD2D3Tl1Co_s0,2076
|
|
42
|
+
modmex_lambda/shared/headers_serializer.py,sha256=Ao-wpx0cmy9E2ACrh7R7RIDUF0h24gax1AMtY_MjIWQ,2505
|
|
43
|
+
modmex_lambda/shared/json_encoder.py,sha256=Mo4tlrhWvlBhhRYoPt2PAP6b_KsEKbk1pK6e5q0gbuk,1297
|
|
44
|
+
modmex_lambda/shared/types.py,sha256=lH3i9MF7EQa1et8dD_qagEjlNzqznNHc0YZawp3toMc,134
|
|
45
|
+
modmex_lambda-0.1.0.dist-info/METADATA,sha256=HOUUd4hbMrZTGBW045M_ltsC9-myVmZiUV9Jt51JHRo,8936
|
|
46
|
+
modmex_lambda-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
47
|
+
modmex_lambda-0.1.0.dist-info/licenses/LICENSE,sha256=_C2TDTOsYeJvE4vn9VB51laKvleBKbdNnn96wJVtXhQ,1063
|
|
48
|
+
modmex_lambda-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 modmex
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|