mdb-engine 0.1.6__py3-none-any.whl → 0.4.12__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.
- mdb_engine/__init__.py +116 -11
- mdb_engine/auth/ARCHITECTURE.md +112 -0
- mdb_engine/auth/README.md +654 -11
- mdb_engine/auth/__init__.py +136 -29
- mdb_engine/auth/audit.py +592 -0
- mdb_engine/auth/base.py +252 -0
- mdb_engine/auth/casbin_factory.py +265 -70
- mdb_engine/auth/config_defaults.py +5 -5
- mdb_engine/auth/config_helpers.py +19 -18
- mdb_engine/auth/cookie_utils.py +12 -16
- mdb_engine/auth/csrf.py +483 -0
- mdb_engine/auth/decorators.py +10 -16
- mdb_engine/auth/dependencies.py +69 -71
- mdb_engine/auth/helpers.py +3 -3
- mdb_engine/auth/integration.py +61 -88
- mdb_engine/auth/jwt.py +11 -15
- mdb_engine/auth/middleware.py +79 -35
- mdb_engine/auth/oso_factory.py +21 -41
- mdb_engine/auth/provider.py +270 -171
- mdb_engine/auth/rate_limiter.py +505 -0
- mdb_engine/auth/restrictions.py +21 -36
- mdb_engine/auth/session_manager.py +24 -41
- mdb_engine/auth/shared_middleware.py +977 -0
- mdb_engine/auth/shared_users.py +775 -0
- mdb_engine/auth/token_lifecycle.py +10 -12
- mdb_engine/auth/token_store.py +17 -32
- mdb_engine/auth/users.py +99 -159
- mdb_engine/auth/utils.py +236 -42
- mdb_engine/cli/commands/generate.py +546 -10
- mdb_engine/cli/commands/validate.py +3 -7
- mdb_engine/cli/utils.py +7 -7
- mdb_engine/config.py +13 -28
- mdb_engine/constants.py +65 -0
- mdb_engine/core/README.md +117 -6
- mdb_engine/core/__init__.py +39 -7
- mdb_engine/core/app_registration.py +31 -50
- mdb_engine/core/app_secrets.py +289 -0
- mdb_engine/core/connection.py +20 -12
- mdb_engine/core/encryption.py +222 -0
- mdb_engine/core/engine.py +2862 -115
- mdb_engine/core/index_management.py +12 -16
- mdb_engine/core/manifest.py +628 -204
- mdb_engine/core/ray_integration.py +436 -0
- mdb_engine/core/seeding.py +13 -21
- mdb_engine/core/service_initialization.py +20 -30
- mdb_engine/core/types.py +40 -43
- mdb_engine/database/README.md +140 -17
- mdb_engine/database/__init__.py +17 -6
- mdb_engine/database/abstraction.py +37 -50
- mdb_engine/database/connection.py +51 -30
- mdb_engine/database/query_validator.py +367 -0
- mdb_engine/database/resource_limiter.py +204 -0
- mdb_engine/database/scoped_wrapper.py +747 -237
- mdb_engine/dependencies.py +427 -0
- mdb_engine/di/__init__.py +34 -0
- mdb_engine/di/container.py +247 -0
- mdb_engine/di/providers.py +206 -0
- mdb_engine/di/scopes.py +139 -0
- mdb_engine/embeddings/README.md +54 -24
- mdb_engine/embeddings/__init__.py +31 -24
- mdb_engine/embeddings/dependencies.py +38 -155
- mdb_engine/embeddings/service.py +78 -75
- mdb_engine/exceptions.py +104 -12
- mdb_engine/indexes/README.md +30 -13
- mdb_engine/indexes/__init__.py +1 -0
- mdb_engine/indexes/helpers.py +11 -11
- mdb_engine/indexes/manager.py +59 -123
- mdb_engine/memory/README.md +95 -4
- mdb_engine/memory/__init__.py +1 -2
- mdb_engine/memory/service.py +363 -1168
- mdb_engine/observability/README.md +4 -2
- mdb_engine/observability/__init__.py +26 -9
- mdb_engine/observability/health.py +17 -17
- mdb_engine/observability/logging.py +10 -10
- mdb_engine/observability/metrics.py +40 -19
- mdb_engine/repositories/__init__.py +34 -0
- mdb_engine/repositories/base.py +325 -0
- mdb_engine/repositories/mongo.py +233 -0
- mdb_engine/repositories/unit_of_work.py +166 -0
- mdb_engine/routing/README.md +1 -1
- mdb_engine/routing/__init__.py +1 -3
- mdb_engine/routing/websockets.py +41 -75
- mdb_engine/utils/__init__.py +3 -1
- mdb_engine/utils/mongo.py +117 -0
- mdb_engine-0.4.12.dist-info/METADATA +492 -0
- mdb_engine-0.4.12.dist-info/RECORD +97 -0
- {mdb_engine-0.1.6.dist-info → mdb_engine-0.4.12.dist-info}/WHEEL +1 -1
- mdb_engine-0.1.6.dist-info/METADATA +0 -213
- mdb_engine-0.1.6.dist-info/RECORD +0 -75
- {mdb_engine-0.1.6.dist-info → mdb_engine-0.4.12.dist-info}/entry_points.txt +0 -0
- {mdb_engine-0.1.6.dist-info → mdb_engine-0.4.12.dist-info}/licenses/LICENSE +0 -0
- {mdb_engine-0.1.6.dist-info → mdb_engine-0.4.12.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mdb-engine
|
|
3
|
+
Version: 0.4.12
|
|
4
|
+
Summary: MongoDB Engine
|
|
5
|
+
Home-page: https://github.com/ranfysvalle02/mdb-engine
|
|
6
|
+
Author: Fabian Valle
|
|
7
|
+
Author-email: Fabian Valle <oblivio.company@gmail.com>
|
|
8
|
+
License: AGPL-3.0
|
|
9
|
+
Project-URL: Homepage, https://github.com/ranfysvalle02/mdb-engine
|
|
10
|
+
Project-URL: Documentation, https://github.com/ranfysvalle02/mdb-engine#readme
|
|
11
|
+
Project-URL: Repository, https://github.com/ranfysvalle02/mdb-engine
|
|
12
|
+
Project-URL: Issues, https://github.com/ranfysvalle02/mdb-engine/issues
|
|
13
|
+
Keywords: mongodb,runtime,engine,database,scoping
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Database
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: motor>=3.0.0
|
|
27
|
+
Requires-Dist: pymongo>=4.0.0
|
|
28
|
+
Requires-Dist: fastapi>=0.100.0
|
|
29
|
+
Requires-Dist: pydantic>=2.0.0
|
|
30
|
+
Requires-Dist: pyjwt>=2.8.0
|
|
31
|
+
Requires-Dist: jsonschema>=4.0.0
|
|
32
|
+
Requires-Dist: bcrypt>=4.0.0
|
|
33
|
+
Requires-Dist: cryptography>=41.0.0
|
|
34
|
+
Requires-Dist: mem0ai>=0.1.7
|
|
35
|
+
Requires-Dist: semantic-text-splitter>=0.9.0
|
|
36
|
+
Requires-Dist: numpy<2.0.0,>=1.0.0
|
|
37
|
+
Requires-Dist: openai>=1.0.0
|
|
38
|
+
Requires-Dist: azure-identity>=1.15.0
|
|
39
|
+
Requires-Dist: click>=8.0.0
|
|
40
|
+
Provides-Extra: casbin
|
|
41
|
+
Requires-Dist: casbin>=1.0.0; extra == "casbin"
|
|
42
|
+
Requires-Dist: casbin-motor-adapter>=0.1.0; extra == "casbin"
|
|
43
|
+
Provides-Extra: oso
|
|
44
|
+
Requires-Dist: oso-cloud>=0.1.0; extra == "oso"
|
|
45
|
+
Provides-Extra: llm
|
|
46
|
+
Provides-Extra: test
|
|
47
|
+
Requires-Dist: pytest>=7.4.0; extra == "test"
|
|
48
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "test"
|
|
49
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == "test"
|
|
50
|
+
Requires-Dist: pytest-mock>=3.11.0; extra == "test"
|
|
51
|
+
Requires-Dist: pytest-timeout>=2.1.0; extra == "test"
|
|
52
|
+
Requires-Dist: pytest-xdist>=3.3.0; extra == "test"
|
|
53
|
+
Requires-Dist: testcontainers>=3.7.0; extra == "test"
|
|
54
|
+
Provides-Extra: dev
|
|
55
|
+
Requires-Dist: ruff<0.6.0,>=0.4.0; extra == "dev"
|
|
56
|
+
Requires-Dist: semgrep>=1.50.0; extra == "dev"
|
|
57
|
+
Provides-Extra: all
|
|
58
|
+
Requires-Dist: casbin>=1.0.0; extra == "all"
|
|
59
|
+
Requires-Dist: casbin-motor-adapter>=0.1.0; extra == "all"
|
|
60
|
+
Requires-Dist: oso-cloud>=0.1.0; extra == "all"
|
|
61
|
+
Dynamic: author
|
|
62
|
+
Dynamic: home-page
|
|
63
|
+
Dynamic: license-file
|
|
64
|
+
Dynamic: requires-python
|
|
65
|
+
|
|
66
|
+
# mdb-engine
|
|
67
|
+
|
|
68
|
+
**The MongoDB Engine for Python Apps** — Auto-sandboxing, index management, and auth in one package.
|
|
69
|
+
|
|
70
|
+
[](https://pypi.org/project/mdb-engine/)
|
|
71
|
+
[](https://www.python.org/downloads/)
|
|
72
|
+
[](https://opensource.org/licenses/AGPL-3.0)
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 🎯 manifest.json: The Key to Everything
|
|
77
|
+
|
|
78
|
+
**`manifest.json` is the foundation of your application.** It's a single configuration file that defines your app's identity, data structure, authentication, indexes, and services. Everything flows from this file.
|
|
79
|
+
|
|
80
|
+
### Your First manifest.json
|
|
81
|
+
|
|
82
|
+
Create a `manifest.json` file with just 3 fields:
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"schema_version": "2.0",
|
|
87
|
+
"slug": "my_app",
|
|
88
|
+
"name": "My App"
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
That's it! This minimal manifest gives you:
|
|
93
|
+
- ✅ Automatic data scoping (all queries filtered by `app_id`)
|
|
94
|
+
- ✅ Collection name prefixing (`db.tasks` → `my_app_tasks`)
|
|
95
|
+
- ✅ App registration and lifecycle management
|
|
96
|
+
|
|
97
|
+
**Learn more**: [Quick Start Guide](docs/QUICK_START.md) | [Manifest Deep Dive](docs/MANIFEST_DEEP_DIVE.md)
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Installation
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
pip install mdb-engine
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 30-Second Quick Start: Build a Todo List API
|
|
110
|
+
|
|
111
|
+
Let's build a complete CRUD todo list app in 3 steps!
|
|
112
|
+
|
|
113
|
+
### Step 1: Create `manifest.json`
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"schema_version": "2.0",
|
|
118
|
+
"slug": "todo_app",
|
|
119
|
+
"name": "Todo List App",
|
|
120
|
+
"managed_indexes": {
|
|
121
|
+
"todos": [
|
|
122
|
+
{
|
|
123
|
+
"type": "regular",
|
|
124
|
+
"keys": {"completed": 1, "created_at": -1},
|
|
125
|
+
"name": "completed_sort"
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Step 2: Create `app.py` with Full CRUD
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
from datetime import datetime
|
|
136
|
+
from pathlib import Path
|
|
137
|
+
from typing import Optional
|
|
138
|
+
|
|
139
|
+
from bson import ObjectId
|
|
140
|
+
from fastapi import Depends, HTTPException
|
|
141
|
+
from pydantic import BaseModel
|
|
142
|
+
|
|
143
|
+
from mdb_engine import MongoDBEngine
|
|
144
|
+
from mdb_engine.dependencies import get_scoped_db
|
|
145
|
+
|
|
146
|
+
# Initialize engine
|
|
147
|
+
engine = MongoDBEngine(
|
|
148
|
+
mongo_uri="mongodb://localhost:27017",
|
|
149
|
+
db_name="my_database"
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
# Create app - manifest.json loaded automatically!
|
|
153
|
+
app = engine.create_app(
|
|
154
|
+
slug="todo_app",
|
|
155
|
+
manifest=Path("manifest.json")
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# Pydantic models
|
|
159
|
+
class TodoCreate(BaseModel):
|
|
160
|
+
title: str
|
|
161
|
+
description: Optional[str] = None
|
|
162
|
+
|
|
163
|
+
class TodoUpdate(BaseModel):
|
|
164
|
+
title: Optional[str] = None
|
|
165
|
+
description: Optional[str] = None
|
|
166
|
+
completed: Optional[bool] = None
|
|
167
|
+
|
|
168
|
+
# CREATE - Add a new todo
|
|
169
|
+
@app.post("/todos")
|
|
170
|
+
async def create_todo(todo: TodoCreate, db=Depends(get_scoped_db)):
|
|
171
|
+
doc = {
|
|
172
|
+
**todo.dict(),
|
|
173
|
+
"completed": False,
|
|
174
|
+
"created_at": datetime.utcnow()
|
|
175
|
+
}
|
|
176
|
+
result = await db.todos.insert_one(doc)
|
|
177
|
+
return {"id": str(result.inserted_id), "message": "Todo created"}
|
|
178
|
+
|
|
179
|
+
# READ - List all todos
|
|
180
|
+
@app.get("/todos")
|
|
181
|
+
async def list_todos(completed: Optional[bool] = None, db=Depends(get_scoped_db)):
|
|
182
|
+
query = {}
|
|
183
|
+
if completed is not None:
|
|
184
|
+
query["completed"] = completed
|
|
185
|
+
|
|
186
|
+
todos = await db.todos.find(query).sort("created_at", -1).to_list(length=100)
|
|
187
|
+
for todo in todos:
|
|
188
|
+
todo["_id"] = str(todo["_id"])
|
|
189
|
+
return {"todos": todos, "count": len(todos)}
|
|
190
|
+
|
|
191
|
+
# READ - Get single todo
|
|
192
|
+
@app.get("/todos/{todo_id}")
|
|
193
|
+
async def get_todo(todo_id: str, db=Depends(get_scoped_db)):
|
|
194
|
+
todo = await db.todos.find_one({"_id": ObjectId(todo_id)})
|
|
195
|
+
if not todo:
|
|
196
|
+
raise HTTPException(status_code=404, detail="Todo not found")
|
|
197
|
+
todo["_id"] = str(todo["_id"])
|
|
198
|
+
return todo
|
|
199
|
+
|
|
200
|
+
# UPDATE - Update a todo
|
|
201
|
+
@app.put("/todos/{todo_id}")
|
|
202
|
+
async def update_todo(todo_id: str, todo: TodoUpdate, db=Depends(get_scoped_db)):
|
|
203
|
+
updates = {k: v for k, v in todo.dict(exclude_unset=True).items() if v is not None}
|
|
204
|
+
if not updates:
|
|
205
|
+
raise HTTPException(status_code=400, detail="No fields to update")
|
|
206
|
+
|
|
207
|
+
updates["updated_at"] = datetime.utcnow()
|
|
208
|
+
result = await db.todos.update_one(
|
|
209
|
+
{"_id": ObjectId(todo_id)},
|
|
210
|
+
{"$set": updates}
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
if result.matched_count == 0:
|
|
214
|
+
raise HTTPException(status_code=404, detail="Todo not found")
|
|
215
|
+
return {"message": "Todo updated"}
|
|
216
|
+
|
|
217
|
+
# DELETE - Delete a todo
|
|
218
|
+
@app.delete("/todos/{todo_id}")
|
|
219
|
+
async def delete_todo(todo_id: str, db=Depends(get_scoped_db)):
|
|
220
|
+
result = await db.todos.delete_one({"_id": ObjectId(todo_id)})
|
|
221
|
+
if result.deleted_count == 0:
|
|
222
|
+
raise HTTPException(status_code=404, detail="Todo not found")
|
|
223
|
+
return {"message": "Todo deleted"}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Step 3: Run It!
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
# Start MongoDB (if not running)
|
|
230
|
+
mongod
|
|
231
|
+
|
|
232
|
+
# Install dependencies
|
|
233
|
+
pip install mdb-engine fastapi uvicorn
|
|
234
|
+
|
|
235
|
+
# Run the app
|
|
236
|
+
uvicorn app:app --reload
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
**Test your API:**
|
|
240
|
+
```bash
|
|
241
|
+
# Create a todo
|
|
242
|
+
curl -X POST http://localhost:8000/todos \
|
|
243
|
+
-H "Content-Type: application/json" \
|
|
244
|
+
-d '{"title": "Buy groceries", "description": "Milk and eggs"}'
|
|
245
|
+
|
|
246
|
+
# List todos
|
|
247
|
+
curl http://localhost:8000/todos
|
|
248
|
+
|
|
249
|
+
# Update a todo (replace {id} with actual ID)
|
|
250
|
+
curl -X PUT http://localhost:8000/todos/{id} \
|
|
251
|
+
-H "Content-Type: application/json" \
|
|
252
|
+
-d '{"completed": true}'
|
|
253
|
+
|
|
254
|
+
# Delete a todo
|
|
255
|
+
curl -X DELETE http://localhost:8000/todos/{id}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**What just happened?**
|
|
259
|
+
- ✅ **Automatic scoping**: All queries filtered by `app_id` — your data is isolated
|
|
260
|
+
- ✅ **Indexes created**: The `completed_sort` index was created automatically
|
|
261
|
+
- ✅ **Lifecycle managed**: Startup/shutdown handled automatically
|
|
262
|
+
- ✅ **Zero boilerplate**: No connection setup, no index scripts, no auth handlers
|
|
263
|
+
|
|
264
|
+
**That's it!** You now have a fully functional, production-ready todo API with automatic data sandboxing, index management, and lifecycle handling.
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Basic Examples
|
|
269
|
+
|
|
270
|
+
### 1. Index Management
|
|
271
|
+
|
|
272
|
+
Define indexes in your `manifest.json` — they're auto-created on startup:
|
|
273
|
+
|
|
274
|
+
```json
|
|
275
|
+
{
|
|
276
|
+
"schema_version": "2.0",
|
|
277
|
+
"slug": "my_app",
|
|
278
|
+
"name": "My App",
|
|
279
|
+
"status": "active",
|
|
280
|
+
"managed_indexes": {
|
|
281
|
+
"tasks": [
|
|
282
|
+
{
|
|
283
|
+
"type": "regular",
|
|
284
|
+
"keys": {"status": 1, "created_at": -1},
|
|
285
|
+
"name": "status_sort"
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
"type": "regular",
|
|
289
|
+
"keys": {"priority": -1},
|
|
290
|
+
"name": "priority_idx"
|
|
291
|
+
}
|
|
292
|
+
],
|
|
293
|
+
"users": [
|
|
294
|
+
{
|
|
295
|
+
"type": "regular",
|
|
296
|
+
"keys": {"email": 1},
|
|
297
|
+
"name": "email_unique",
|
|
298
|
+
"unique": true
|
|
299
|
+
}
|
|
300
|
+
]
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
Supported index types: `regular`, `text`, `vector`, `ttl`, `compound`.
|
|
306
|
+
|
|
307
|
+
### 2. CRUD Operations (Auto-Scoped)
|
|
308
|
+
|
|
309
|
+
All database operations are automatically scoped to your app. Use `Depends(get_scoped_db)` in route handlers:
|
|
310
|
+
|
|
311
|
+
```python
|
|
312
|
+
from mdb_engine.dependencies import get_scoped_db
|
|
313
|
+
|
|
314
|
+
@app.post("/tasks")
|
|
315
|
+
async def create_task(task: dict, db=Depends(get_scoped_db)):
|
|
316
|
+
result = await db.tasks.insert_one(task)
|
|
317
|
+
return {"id": str(result.inserted_id)}
|
|
318
|
+
|
|
319
|
+
@app.get("/tasks")
|
|
320
|
+
async def list_tasks(db=Depends(get_scoped_db)):
|
|
321
|
+
return await db.tasks.find({"status": "pending"}).to_list(length=10)
|
|
322
|
+
|
|
323
|
+
@app.put("/tasks/{task_id}")
|
|
324
|
+
async def update_task(task_id: str, db=Depends(get_scoped_db)):
|
|
325
|
+
await db.tasks.update_one({"_id": task_id}, {"$set": {"status": "done"}})
|
|
326
|
+
return {"updated": True}
|
|
327
|
+
|
|
328
|
+
@app.delete("/tasks/{task_id}")
|
|
329
|
+
async def delete_task(task_id: str, db=Depends(get_scoped_db)):
|
|
330
|
+
await db.tasks.delete_one({"_id": task_id})
|
|
331
|
+
return {"deleted": True}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
**What happens under the hood:**
|
|
335
|
+
```python
|
|
336
|
+
# You write:
|
|
337
|
+
await db.tasks.find({}).to_list(length=10)
|
|
338
|
+
|
|
339
|
+
# Engine executes:
|
|
340
|
+
# Collection: my_app_tasks
|
|
341
|
+
# Query: {"app_id": "my_app"}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### 3. Health Checks
|
|
345
|
+
|
|
346
|
+
Built-in observability:
|
|
347
|
+
|
|
348
|
+
```python
|
|
349
|
+
@app.get("/health")
|
|
350
|
+
async def health():
|
|
351
|
+
status = await engine.get_health_status()
|
|
352
|
+
return {"status": status.get("status", "unknown")}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## Why mdb-engine?
|
|
358
|
+
|
|
359
|
+
- **manifest.json is everything** — Single source of truth for your entire app configuration
|
|
360
|
+
- **Zero boilerplate** — No more connection setup, index creation scripts, or auth handlers
|
|
361
|
+
- **Data isolation** — Multi-tenant ready with automatic app sandboxing
|
|
362
|
+
- **Manifest-driven** — Define your app's "DNA" in JSON, not scattered code
|
|
363
|
+
- **Incremental adoption** — Start minimal, add features as needed
|
|
364
|
+
- **No lock-in** — Standard Motor/PyMongo underneath; export anytime with `mongodump --query='{"app_id":"my_app"}'`
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## Advanced Features
|
|
369
|
+
|
|
370
|
+
| Feature | Description | Learn More |
|
|
371
|
+
|---------|-------------|------------|
|
|
372
|
+
| **Authentication** | JWT + Casbin/OSO RBAC | [Auth Guide](https://github.com/ranfysvalle02/mdb-engine/blob/main/docs/AUTHZ.md) |
|
|
373
|
+
| **Vector Search** | Atlas Vector Search + embeddings | [RAG Example](https://github.com/ranfysvalle02/mdb-engine/tree/main/examples/basic/interactive_rag) |
|
|
374
|
+
| **Memory Service** | Persistent AI memory with Mem0 | [Chat Example](https://github.com/ranfysvalle02/mdb-engine/tree/main/examples/basic/chit_chat) |
|
|
375
|
+
| **WebSockets** | Real-time updates from manifest | [Docs](https://github.com/ranfysvalle02/mdb-engine/blob/main/docs/ARCHITECTURE.md) |
|
|
376
|
+
| **Multi-App** | Secure cross-app data access | [Multi-App Example](https://github.com/ranfysvalle02/mdb-engine/tree/main/examples/advanced/multi_app) |
|
|
377
|
+
| **SSO** | Shared auth across apps | [Shared Auth Example](https://github.com/ranfysvalle02/mdb-engine/tree/main/examples/advanced/multi_app_shared) |
|
|
378
|
+
|
|
379
|
+
### AppContext — All Services in One Place ✨
|
|
380
|
+
|
|
381
|
+
```python
|
|
382
|
+
from fastapi import Depends
|
|
383
|
+
from mdb_engine.dependencies import AppContext
|
|
384
|
+
|
|
385
|
+
@app.post("/ai-chat")
|
|
386
|
+
async def chat(query: str, ctx: AppContext = Depends()):
|
|
387
|
+
user = ctx.require_user() # 401 if not logged in
|
|
388
|
+
ctx.require_role("user") # 403 if missing role
|
|
389
|
+
|
|
390
|
+
# Everything available: ctx.db, ctx.embedding_service, ctx.memory, ctx.llm
|
|
391
|
+
if ctx.llm:
|
|
392
|
+
response = ctx.llm.chat.completions.create(
|
|
393
|
+
model=ctx.llm_model,
|
|
394
|
+
messages=[{"role": "user", "content": query}]
|
|
395
|
+
)
|
|
396
|
+
return {"response": response.choices[0].message.content}
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
## Full Examples
|
|
402
|
+
|
|
403
|
+
Clone and run:
|
|
404
|
+
|
|
405
|
+
```bash
|
|
406
|
+
git clone https://github.com/ranfysvalle02/mdb-engine.git
|
|
407
|
+
cd mdb-engine/examples/basic/chit_chat
|
|
408
|
+
docker-compose up --build
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### Basic Examples
|
|
412
|
+
|
|
413
|
+
| Example | Description |
|
|
414
|
+
|---------|-------------|
|
|
415
|
+
| [chit_chat](https://github.com/ranfysvalle02/mdb-engine/tree/main/examples/basic/chit_chat) | AI chat with persistent memory |
|
|
416
|
+
| [interactive_rag](https://github.com/ranfysvalle02/mdb-engine/tree/main/examples/basic/interactive_rag) | RAG with vector search |
|
|
417
|
+
| [oso_hello_world](https://github.com/ranfysvalle02/mdb-engine/tree/main/examples/basic/oso_hello_world) | OSO Cloud authorization |
|
|
418
|
+
| [parallax](https://github.com/ranfysvalle02/mdb-engine/tree/main/examples/basic/parallax) | Dynamic schema generation |
|
|
419
|
+
| [vector_hacking](https://github.com/ranfysvalle02/mdb-engine/tree/main/examples/basic/vector_hacking) | Vector embeddings & attacks |
|
|
420
|
+
|
|
421
|
+
### Advanced Examples
|
|
422
|
+
|
|
423
|
+
| Example | Description |
|
|
424
|
+
|---------|-------------|
|
|
425
|
+
| [simple_app](https://github.com/ranfysvalle02/mdb-engine/tree/main/examples/advanced/simple_app) | Task management with `create_app()` pattern |
|
|
426
|
+
| [multi_app](https://github.com/ranfysvalle02/mdb-engine/tree/main/examples/advanced/multi_app) | Multi-tenant with cross-app access |
|
|
427
|
+
| [multi_app_shared](https://github.com/ranfysvalle02/mdb-engine/tree/main/examples/advanced/multi_app_shared) | SSO with shared user pool |
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
## Manual Setup (Alternative)
|
|
432
|
+
|
|
433
|
+
If you need more control over the FastAPI lifecycle:
|
|
434
|
+
|
|
435
|
+
```python
|
|
436
|
+
from pathlib import Path
|
|
437
|
+
from fastapi import FastAPI
|
|
438
|
+
from mdb_engine import MongoDBEngine
|
|
439
|
+
|
|
440
|
+
app = FastAPI()
|
|
441
|
+
engine = MongoDBEngine(mongo_uri="mongodb://localhost:27017", db_name="my_database")
|
|
442
|
+
|
|
443
|
+
@app.on_event("startup")
|
|
444
|
+
async def startup():
|
|
445
|
+
await engine.initialize()
|
|
446
|
+
manifest = await engine.load_manifest(Path("manifest.json"))
|
|
447
|
+
await engine.register_app(manifest, create_indexes=True)
|
|
448
|
+
|
|
449
|
+
@app.on_event("shutdown")
|
|
450
|
+
async def shutdown():
|
|
451
|
+
await engine.shutdown()
|
|
452
|
+
|
|
453
|
+
@app.get("/items")
|
|
454
|
+
async def get_items():
|
|
455
|
+
db = engine.get_scoped_db("my_app")
|
|
456
|
+
return await db.items.find({}).to_list(length=10)
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
---
|
|
460
|
+
|
|
461
|
+
## Understanding manifest.json
|
|
462
|
+
|
|
463
|
+
Your `manifest.json` is the heart of your application. It defines:
|
|
464
|
+
|
|
465
|
+
- **App Identity**: `slug`, `name`, `description`
|
|
466
|
+
- **Data Access**: `data_access.read_scopes`, `data_access.write_scope`
|
|
467
|
+
- **Indexes**: `managed_indexes` (regular, vector, text, TTL, compound)
|
|
468
|
+
- **Authentication**: `auth.policy`, `auth.users` (Casbin/OSO, demo users)
|
|
469
|
+
- **AI Services**: `embedding_config`, `memory_config`
|
|
470
|
+
- **Real-time**: `websockets` endpoints
|
|
471
|
+
- **CORS**: `cors` settings
|
|
472
|
+
|
|
473
|
+
**Start minimal, grow as needed.** You can begin with just `slug`, `name`, and `schema_version`, then add features incrementally.
|
|
474
|
+
|
|
475
|
+
**📖 Learn More:**
|
|
476
|
+
- [Quick Start Guide](docs/QUICK_START.md) - Get started with manifest.json
|
|
477
|
+
- [Manifest Deep Dive](docs/MANIFEST_DEEP_DIVE.md) - Comprehensive manifest.json guide
|
|
478
|
+
- [Examples](examples/) - Real-world manifest.json files
|
|
479
|
+
|
|
480
|
+
---
|
|
481
|
+
|
|
482
|
+
## Links
|
|
483
|
+
|
|
484
|
+
- [GitHub Repository](https://github.com/ranfysvalle02/mdb-engine)
|
|
485
|
+
- [Documentation](https://github.com/ranfysvalle02/mdb-engine/tree/main/docs)
|
|
486
|
+
- [All Examples](https://github.com/ranfysvalle02/mdb-engine/tree/main/examples)
|
|
487
|
+
- [Quick Start Guide](docs/QUICK_START.md) - **Start here!**
|
|
488
|
+
- [Contributing](CONTRIBUTING.md)
|
|
489
|
+
|
|
490
|
+
---
|
|
491
|
+
|
|
492
|
+
**Stop building scaffolding. Start building features.**
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
mdb_engine/README.md,sha256=T3EFGcPopY9LslYW3lxgG3hohWkAOmBNbYG0FDMUJiY,3502
|
|
2
|
+
mdb_engine/__init__.py,sha256=Egwc1COlKqmKB-qVUHAjWfJFmEg6iYT4DKE6m5hgpso,3460
|
|
3
|
+
mdb_engine/config.py,sha256=DTAyxfKB8ogyI0v5QR9Y-SJOgXQr_eDBCKxNBSqEyLc,7269
|
|
4
|
+
mdb_engine/constants.py,sha256=eaotvW57TVOg7rRbLziGrVNoP7adgw_G9iVByHezc_A,7837
|
|
5
|
+
mdb_engine/dependencies.py,sha256=MJuYQhZ9ZGzXlip1ha5zba9Rvn04HDPWahJFJH81Q2s,14107
|
|
6
|
+
mdb_engine/exceptions.py,sha256=NkBSdTBNP9bVTtI6w6mAoEfeVZDq-Bg7vCF2L26ZDZo,8442
|
|
7
|
+
mdb_engine/auth/ARCHITECTURE.md,sha256=JXZsjEIpNz4Szk18KaOiEabhEuz1pmYWXQRN-EJEHDM,4076
|
|
8
|
+
mdb_engine/auth/README.md,sha256=IVlUOat96V3yM6wk4T-u4GxJ4-WF05eBSJBlvIexyBo,37285
|
|
9
|
+
mdb_engine/auth/__init__.py,sha256=QemWqAVvqlxjF-UbzMTGP5AUOeuaAsUEtK4PMxmozmA,5852
|
|
10
|
+
mdb_engine/auth/audit.py,sha256=UQ0Bj5Zxp5et9A21YZCVkUjaABFqO1CXaMrWxNcdxm8,17352
|
|
11
|
+
mdb_engine/auth/base.py,sha256=4E3XkbruZLG9lc6aC56w0ypjnfiR5RbtjQKwn4am8to,7418
|
|
12
|
+
mdb_engine/auth/casbin_factory.py,sha256=oZLHIPyVA1hiho__ledRVDoBisaZgo96WZIKa0-kQic,16610
|
|
13
|
+
mdb_engine/auth/casbin_models.py,sha256=7XtFmRBhhjw1nKprnluvjyJoTj5fzdPeQwVvo6fI-r0,955
|
|
14
|
+
mdb_engine/auth/config_defaults.py,sha256=1YI_hIHuTiEXpkEYMcufNHdLr1oxPiJylg3CKrJCSGY,2012
|
|
15
|
+
mdb_engine/auth/config_helpers.py,sha256=Qharb2YagLOKDGtE7XhYRDbBoQ_KGykrcIKrsOwWIJ4,6303
|
|
16
|
+
mdb_engine/auth/cookie_utils.py,sha256=j04qXq5GiJrnnJUAP5Z_N1CAFbx9CZiyF5u9xIiQ3vo,4876
|
|
17
|
+
mdb_engine/auth/csrf.py,sha256=7zLiX9IEvgBXp3DjVBmcaYATS6cTelQReUYYkiVas6M,17626
|
|
18
|
+
mdb_engine/auth/decorators.py,sha256=LkVVEuRrT0Iz8EwctN14BEi3fSV-xtN6DaGXgtbiYYo,12287
|
|
19
|
+
mdb_engine/auth/dependencies.py,sha256=JB1iYvZJgTR6gcaiGe_GJFCS6NdUKMxWBZRv6vVxnzw,27112
|
|
20
|
+
mdb_engine/auth/helpers.py,sha256=BCrid985cYh-3h5ZMUV9TES0q40uJXio4oYKQZta7KA,1970
|
|
21
|
+
mdb_engine/auth/integration.py,sha256=6PMjGKS71bl-OrwxG_kksY1069jB9nNZZNFs2C2H2qk,22740
|
|
22
|
+
mdb_engine/auth/jwt.py,sha256=HKcGOaza62zdIQx0mHLV9zBSibCLlrM6NnCXg1HCGUc,7206
|
|
23
|
+
mdb_engine/auth/middleware.py,sha256=e21eZQYrgNPChb0uL6Uw1hV2Rzw92D9ZWAkqWv4nHSE,10866
|
|
24
|
+
mdb_engine/auth/oso_factory.py,sha256=EwRgN1OjjcwZPU4In35Zwrc5Qsm_aCUjyR3nxNqqwiw,11264
|
|
25
|
+
mdb_engine/auth/provider.py,sha256=FOSHn-jp4VYtxvmjnzho5kH6y-xDKWbcKUorYRRl1C4,26576
|
|
26
|
+
mdb_engine/auth/rate_limiter.py,sha256=l3EYZE1Kz9yVfZwNrKq_1AgdD7GXB1WOLSqqGQVSSgA,15808
|
|
27
|
+
mdb_engine/auth/restrictions.py,sha256=tOyQBO_w0bK9zmTsOPZf9cbvh4oITvpNfSxIXt-XrcU,8824
|
|
28
|
+
mdb_engine/auth/session_manager.py,sha256=ywWJjTarm-obgJ3zO3s-1cdqEYe0XrozlY00q_yMJ8I,15396
|
|
29
|
+
mdb_engine/auth/shared_middleware.py,sha256=0iSbRkwdivL1NIj7Gr161qPJiqcw0JafOpZLCkXjT7k,37633
|
|
30
|
+
mdb_engine/auth/shared_users.py,sha256=KTc4D9zRaYaIVto7PqyWd5RT4J97cp6AnJ5i_PR_7eg,27775
|
|
31
|
+
mdb_engine/auth/token_lifecycle.py,sha256=Q9S1X2Y6W7Ckt5PvyYXswBRh2Tg9DGpyRv_3Xve7VYQ,6708
|
|
32
|
+
mdb_engine/auth/token_store.py,sha256=-B8j5RH5YEoKsswF4rnMoI51BaxMe4icke3kuehXmcI,9121
|
|
33
|
+
mdb_engine/auth/users.py,sha256=t9Us2_A_wKOL9qy1O_SBwTvapAyNztn0v8padxJVq6A,49891
|
|
34
|
+
mdb_engine/auth/utils.py,sha256=g7fXkxIb8yuvlZrhKeQxAR0KxiUakXRK5WtKG4opihk,26019
|
|
35
|
+
mdb_engine/cli/__init__.py,sha256=PANRi4THmL34d1mawlqxIrnuItXMdqoMTq5Z1zHd7rM,301
|
|
36
|
+
mdb_engine/cli/main.py,sha256=Y5ELFhvsr8zxFWv4WScOGNHiLUTdSXAJeUFLpRXCelg,811
|
|
37
|
+
mdb_engine/cli/utils.py,sha256=bNRGJgdzxUjXAOVe1aoxWJ5M_IqtAE-eW4pfAkwiDDM,2760
|
|
38
|
+
mdb_engine/cli/commands/__init__.py,sha256=ZSzMhKdV9ILD5EbOSxDV9nURHo1e4bQ0c8AWpqsTEqM,115
|
|
39
|
+
mdb_engine/cli/commands/generate.py,sha256=VEcn7qNQkIPQlLEK3oXUBgYMwD-G0FyomXQcWTtKsbs,17304
|
|
40
|
+
mdb_engine/cli/commands/migrate.py,sha256=VqNiobSq-ykUhv7NyHJZ-wZ60a8X0B6OqXz8OACsCr0,2077
|
|
41
|
+
mdb_engine/cli/commands/show.py,sha256=-PmyMfzzG1HP-PsD9n8LECyxwvlXypNS3g_VDwFg4oY,1914
|
|
42
|
+
mdb_engine/cli/commands/validate.py,sha256=tD8GkhuW8LKsRMUXvBs-wvVWQunw1XFlLvbpE_SQ9Zg,1688
|
|
43
|
+
mdb_engine/core/README.md,sha256=cl19Sw4Hj-BPBsh_FIhPpop_6S88V-KaHC6rnUCx8xw,17039
|
|
44
|
+
mdb_engine/core/__init__.py,sha256=xhnXyXWZ0a2Qr49QrYvLE5QuqSalcpo05hHHRVtDz_M,1952
|
|
45
|
+
mdb_engine/core/app_registration.py,sha256=7szt2a7aBkpSppjmhdkkPPYMKGKo0MkLKZeEeWk-Rq8,13356
|
|
46
|
+
mdb_engine/core/app_secrets.py,sha256=bo-syg9UUATibNyXEZs-0TTYWG-JaY-2S0yNSGA12n0,10524
|
|
47
|
+
mdb_engine/core/connection.py,sha256=XnwuPG34pJ7kJGJ84T0mhj1UZ6_CLz_9qZf6NRYGIS8,8346
|
|
48
|
+
mdb_engine/core/encryption.py,sha256=RZ5LPF5g28E3ZBn6v1IMw_oas7u9YGFtBcEj8lTi9LM,7515
|
|
49
|
+
mdb_engine/core/engine.py,sha256=ydYt2z53scf4GzufD8rY5X6gSJEF80VSDm1QDR2pwWQ,151507
|
|
50
|
+
mdb_engine/core/index_management.py,sha256=9-r7MIy3JnjQ35sGqsbj8K_I07vAUWtAVgSWC99lJcE,5555
|
|
51
|
+
mdb_engine/core/manifest.py,sha256=jguhjVPAHMZGxOJcdSGouv9_XiKmxUjDmyjn2yXHCj4,139205
|
|
52
|
+
mdb_engine/core/ray_integration.py,sha256=vexYOzztscvRYje1xTNmXJbi99oJxCaVJAwKfTNTF_E,13610
|
|
53
|
+
mdb_engine/core/seeding.py,sha256=c5IhdwlqUf_4Q5FFTAhPLaHPaUr_Txo3z_DUwZmWsFs,6421
|
|
54
|
+
mdb_engine/core/service_initialization.py,sha256=rtb6BaPvFqomwT_s7bdbbvqi5m74llT0LkJFEhVG9Gg,12996
|
|
55
|
+
mdb_engine/core/types.py,sha256=x7ahgb61vXVikn7nKHWGxQRW3StMG9lTHwr-Uvpnt_g,11150
|
|
56
|
+
mdb_engine/database/README.md,sha256=-31mVxBeVQaYsF3AD1-gQbD2NCYVcPjdFoA6sZ6b02Y,19354
|
|
57
|
+
mdb_engine/database/__init__.py,sha256=rrc3eZFli3K2zrvVdDbMBi8YkmoHYzP6JNT0AUBE5VU,981
|
|
58
|
+
mdb_engine/database/abstraction.py,sha256=H6f2WYY80r3onqN6s139uDSyG9W_QpadaoQ84hJuG1E,23438
|
|
59
|
+
mdb_engine/database/connection.py,sha256=-6FL6QwIlZxd7Sm7kbTaeISNrDD8A4dHGSbIEkKzqF0,15071
|
|
60
|
+
mdb_engine/database/query_validator.py,sha256=5xcGWd3Csk2qgvgJTIccEsc3bV10WNZUEKaI2loLwQs,13239
|
|
61
|
+
mdb_engine/database/resource_limiter.py,sha256=BCIACGexVRVhUcDERQFmg1LW8CPBQos_ZvmfLcJ4Opk,6905
|
|
62
|
+
mdb_engine/database/scoped_wrapper.py,sha256=5ToXG2NSFFG9Js87sRPkwE51XIUJwVUGgSta03W2t9A,94661
|
|
63
|
+
mdb_engine/di/__init__.py,sha256=uy9Q153a0QE678TkJ_AEwLuxPY3OyEum2I42_JsuwrI,912
|
|
64
|
+
mdb_engine/di/container.py,sha256=imr_3buWcJDNCEgn4-HTQvBV8DOU7gz8UfghI8FpqUA,7410
|
|
65
|
+
mdb_engine/di/providers.py,sha256=-KPYM4lz8pBxh3J1fuNJyFHwBuqL1vvWk7VgJxew4uo,5927
|
|
66
|
+
mdb_engine/di/scopes.py,sha256=pZgdkZ9ziW-vYCMvecC8Mv3Ud_Xk4ScsDYZ2eWHvar0,4165
|
|
67
|
+
mdb_engine/embeddings/README.md,sha256=XjGWUXSdbSpXCAEEVfYmcJoFKBVmXDoM3eTjenrM5Z0,5926
|
|
68
|
+
mdb_engine/embeddings/__init__.py,sha256=BM8tfcekVZv_iPQj3OuZBQ3hHr0eRQetNLEMysRTZkE,2129
|
|
69
|
+
mdb_engine/embeddings/dependencies.py,sha256=0LIEU5L1jvZBKO4yhYxh4WxDhzJaZI9ohZGBNa6B7IY,2182
|
|
70
|
+
mdb_engine/embeddings/service.py,sha256=3JUqAU-e5TVLOpry5MdP-O4q6tHoqkXA8PyvcxqFoik,26983
|
|
71
|
+
mdb_engine/indexes/README.md,sha256=r7duq-1vtqHhBk1cwoBMYYh_dfTzxiaQaPE3mLB_3JQ,15341
|
|
72
|
+
mdb_engine/indexes/__init__.py,sha256=9QFJ6qo_yD26dZcKyKjj-hhesFpaomBt-mWTtYTQvqc,613
|
|
73
|
+
mdb_engine/indexes/helpers.py,sha256=tJHqDm18jKLrW-P2ofmnUnaf4_-V5xDLjqP_WU8W9MM,4190
|
|
74
|
+
mdb_engine/indexes/manager.py,sha256=XSjvFNMOv67yey5Vi4mKBt6_w4b6Hqtv24fiAXnfLi0,32460
|
|
75
|
+
mdb_engine/memory/README.md,sha256=uOE4SnPyq8TdoxGrttof5fSj2KSqnrgzUorMCV_1wg0,13624
|
|
76
|
+
mdb_engine/memory/__init__.py,sha256=e4kAYgxd_-WAH8GovTwjEBO9hvASu_kXEupMgksAL-U,1008
|
|
77
|
+
mdb_engine/memory/service.py,sha256=l2bkKVN9AyUjO9K9ykb5BK9dZjs3ns78FJLOD5LajsY,18454
|
|
78
|
+
mdb_engine/observability/README.md,sha256=CMgQaC1H8ESmCitfbhJifz6-XoXH_FPNE4MvuZ-oFas,13085
|
|
79
|
+
mdb_engine/observability/__init__.py,sha256=jjLsrW6Gy2ayrbfLrgHsDB61NxWWkYLHwv0q-N3fxjA,1213
|
|
80
|
+
mdb_engine/observability/health.py,sha256=eFd8a-Rv3NWML0EDdZ8thZWTiqP_FUZbub97hV2z57g,9190
|
|
81
|
+
mdb_engine/observability/logging.py,sha256=lJV9iIk-cKb87LEfeMAIP0PPN5vg8-pdRdPzwD29SAM,4039
|
|
82
|
+
mdb_engine/observability/metrics.py,sha256=_5ZlObbYNgEanWvt-n0wIg9QOAnHBpePs_wKysSoJxQ,10728
|
|
83
|
+
mdb_engine/repositories/__init__.py,sha256=048N4QmFLVhJyLdYrWHTTBqujhaF--B8g0z6fUSMuJs,858
|
|
84
|
+
mdb_engine/repositories/base.py,sha256=9AP3baJzJeU2zIhh04TfvP1f3q5HyHdkrSW11xrcY70,8514
|
|
85
|
+
mdb_engine/repositories/mongo.py,sha256=Wg32_6v0KHAHumhz5z8QkoqJRWAMJFA7Y2lYIJ7LZIk,7142
|
|
86
|
+
mdb_engine/repositories/unit_of_work.py,sha256=XvmwGOspEDj4hsfOULPsQKjB1QZqh83TJo6vGV4tiqU,5118
|
|
87
|
+
mdb_engine/routing/README.md,sha256=WVvTQXDq0amryrjkCu0wP_piOEwFjLukjmPz2mroWHY,13658
|
|
88
|
+
mdb_engine/routing/__init__.py,sha256=reupjHi_RTc2ZBA4AH5XzobAmqy4EQIsfSUcTkFknUM,2438
|
|
89
|
+
mdb_engine/routing/websockets.py,sha256=3X4OjQv_Nln4UmeifJky0gFhMG8A6alR77I8g1iIOLY,29311
|
|
90
|
+
mdb_engine/utils/__init__.py,sha256=lDxQSGqkV4fVw5TWIk6FA6_eey_ZnEtMY0fir3cpAe8,236
|
|
91
|
+
mdb_engine/utils/mongo.py,sha256=Oqtv4tQdpiiZzrilGLEYQPo8Vmh8WsTQypxQs8Of53s,3369
|
|
92
|
+
mdb_engine-0.4.12.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
|
|
93
|
+
mdb_engine-0.4.12.dist-info/METADATA,sha256=Jrn7XyZ1ZgCzyN5F5oVDXbo4xngGUCEUjPCW6dvYJyc,15811
|
|
94
|
+
mdb_engine-0.4.12.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
95
|
+
mdb_engine-0.4.12.dist-info/entry_points.txt,sha256=INCbYdFbBzJalwPwxliEzLmPfR57IvQ7RAXG_pn8cL8,48
|
|
96
|
+
mdb_engine-0.4.12.dist-info/top_level.txt,sha256=PH0UEBwTtgkm2vWvC9He_EOMn7hVn_Wg_Jyc0SmeO8k,11
|
|
97
|
+
mdb_engine-0.4.12.dist-info/RECORD,,
|