mdb-engine 0.2.3__py3-none-any.whl → 0.2.4__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.
@@ -4,4 +4,6 @@ Utility functions and helpers for MDB Engine.
4
4
  This module provides utility functions used across the MDB Engine codebase.
5
5
  """
6
6
 
7
- __all__ = []
7
+ from .mongo import clean_mongo_doc, clean_mongo_docs
8
+
9
+ __all__ = ["clean_mongo_doc", "clean_mongo_docs"]
@@ -0,0 +1,117 @@
1
+ """
2
+ MongoDB utility functions for MDB Engine.
3
+
4
+ This module provides utility functions for working with MongoDB documents,
5
+ including JSON serialization helpers.
6
+ """
7
+
8
+ from typing import Any
9
+
10
+
11
+ def clean_mongo_doc(doc: dict[str, Any] | None) -> dict[str, Any] | None:
12
+ """
13
+ Convert MongoDB document to JSON-serializable format.
14
+
15
+ Recursively converts MongoDB-specific types to JSON-compatible types:
16
+ - ObjectId -> str
17
+ - datetime -> ISO format string
18
+ - Nested dictionaries and lists are processed recursively
19
+
20
+ Args:
21
+ doc: MongoDB document (dict) or None
22
+
23
+ Returns:
24
+ Cleaned document with all MongoDB types converted, or None if input was None
25
+
26
+ Example:
27
+ ```python
28
+ from mdb_engine.utils import clean_mongo_doc
29
+
30
+ # MongoDB document with ObjectId and datetime
31
+ doc = {
32
+ "_id": ObjectId("507f1f77bcf86cd799439011"),
33
+ "name": "John",
34
+ "created_at": datetime(2024, 1, 1, 12, 0, 0),
35
+ "nested": {
36
+ "id": ObjectId("507f1f77bcf86cd799439012")
37
+ }
38
+ }
39
+
40
+ # Convert to JSON-serializable format
41
+ cleaned = clean_mongo_doc(doc)
42
+ # {
43
+ # "_id": "507f1f77bcf86cd799439011",
44
+ # "name": "John",
45
+ # "created_at": "2024-01-01T12:00:00",
46
+ # "nested": {
47
+ # "id": "507f1f77bcf86cd799439012"
48
+ # }
49
+ # }
50
+ ```
51
+ """
52
+ from datetime import datetime
53
+
54
+ from bson import ObjectId
55
+
56
+ if doc is None:
57
+ return None
58
+
59
+ if not isinstance(doc, dict):
60
+ # If it's not a dict, try to convert it
61
+ if isinstance(doc, ObjectId):
62
+ return str(doc)
63
+ elif isinstance(doc, datetime):
64
+ return doc.isoformat() if hasattr(doc, "isoformat") else str(doc)
65
+ else:
66
+ return doc
67
+
68
+ cleaned: dict[str, Any] = {}
69
+
70
+ for key, value in doc.items():
71
+ if isinstance(value, ObjectId):
72
+ cleaned[key] = str(value)
73
+ elif isinstance(value, datetime):
74
+ cleaned[key] = value.isoformat() if hasattr(value, "isoformat") else str(value)
75
+ elif isinstance(value, dict):
76
+ cleaned[key] = clean_mongo_doc(value)
77
+ elif isinstance(value, list):
78
+ cleaned[key] = [
79
+ clean_mongo_doc(item)
80
+ if isinstance(item, dict)
81
+ else (
82
+ str(item)
83
+ if isinstance(item, ObjectId)
84
+ else (item.isoformat() if isinstance(item, datetime) else item)
85
+ )
86
+ for item in value
87
+ ]
88
+ else:
89
+ cleaned[key] = value
90
+
91
+ return cleaned
92
+
93
+
94
+ def clean_mongo_docs(docs: list[dict[str, Any]]) -> list[dict[str, Any]]:
95
+ """
96
+ Convert a list of MongoDB documents to JSON-serializable format.
97
+
98
+ Convenience function that applies clean_mongo_doc to each document in a list.
99
+
100
+ Args:
101
+ docs: List of MongoDB documents
102
+
103
+ Returns:
104
+ List of cleaned documents
105
+
106
+ Example:
107
+ ```python
108
+ from mdb_engine.utils import clean_mongo_docs
109
+
110
+ # List of MongoDB documents
111
+ docs = await db.collection.find({}).to_list(length=10)
112
+
113
+ # Convert all to JSON-serializable format
114
+ cleaned = clean_mongo_docs(docs)
115
+ ```
116
+ """
117
+ return [clean_mongo_doc(doc) for doc in docs]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mdb-engine
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: MongoDB Engine
5
5
  Home-page: https://github.com/ranfysvalle02/mdb-engine
6
6
  Author: Fabian Valle
@@ -73,6 +73,31 @@ Dynamic: requires-python
73
73
 
74
74
  ---
75
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
+
76
101
  ## Installation
77
102
 
78
103
  ```bash
@@ -83,28 +108,55 @@ pip install mdb-engine
83
108
 
84
109
  ## 30-Second Quick Start
85
110
 
111
+ **Step 1**: Create your `manifest.json`:
112
+
113
+ ```json
114
+ {
115
+ "schema_version": "2.0",
116
+ "slug": "my_app",
117
+ "name": "My App",
118
+ "managed_indexes": {
119
+ "tasks": [
120
+ {
121
+ "type": "regular",
122
+ "keys": {"status": 1, "created_at": -1},
123
+ "name": "status_sort"
124
+ }
125
+ ]
126
+ }
127
+ }
128
+ ```
129
+
130
+ **Step 2**: Create your FastAPI app:
131
+
86
132
  ```python
87
133
  from pathlib import Path
88
134
  from fastapi import Depends
89
135
  from mdb_engine import MongoDBEngine
90
136
  from mdb_engine.dependencies import get_scoped_db
91
137
 
92
- # 1. Initialize the engine
138
+ # Initialize the engine
93
139
  engine = MongoDBEngine(
94
140
  mongo_uri="mongodb://localhost:27017",
95
141
  db_name="my_database"
96
142
  )
97
143
 
98
- # 2. Create a FastAPI app with automatic lifecycle management
144
+ # Create app - manifest.json is loaded automatically!
99
145
  app = engine.create_app(slug="my_app", manifest=Path("manifest.json"))
100
146
 
101
- # 3. Use request-scoped dependencies - all queries automatically isolated
147
+ # Use request-scoped dependencies - all queries automatically isolated
102
148
  @app.post("/tasks")
103
149
  async def create_task(task: dict, db=Depends(get_scoped_db)):
104
150
  result = await db.tasks.insert_one(task)
105
151
  return {"id": str(result.inserted_id)}
106
152
  ```
107
153
 
154
+ **What just happened?**
155
+ - ✅ Engine loaded your `manifest.json`
156
+ - ✅ Indexes created automatically from `managed_indexes`
157
+ - ✅ Database queries automatically scoped to your app
158
+ - ✅ Lifecycle management handled (startup/shutdown)
159
+
108
160
  That's it. Your data is automatically sandboxed, indexes are created, and cleanup is handled.
109
161
 
110
162
  ---
@@ -200,9 +252,11 @@ async def health():
200
252
 
201
253
  ## Why mdb-engine?
202
254
 
255
+ - **manifest.json is everything** — Single source of truth for your entire app configuration
203
256
  - **Zero boilerplate** — No more connection setup, index creation scripts, or auth handlers
204
257
  - **Data isolation** — Multi-tenant ready with automatic app sandboxing
205
258
  - **Manifest-driven** — Define your app's "DNA" in JSON, not scattered code
259
+ - **Incremental adoption** — Start minimal, add features as needed
206
260
  - **No lock-in** — Standard Motor/PyMongo underneath; export anytime with `mongodump --query='{"app_id":"my_app"}'`
207
261
 
208
262
  ---
@@ -300,13 +354,34 @@ async def get_items():
300
354
 
301
355
  ---
302
356
 
357
+ ## Understanding manifest.json
358
+
359
+ Your `manifest.json` is the heart of your application. It defines:
360
+
361
+ - **App Identity**: `slug`, `name`, `description`
362
+ - **Data Access**: `data_access.read_scopes`, `data_access.write_scope`
363
+ - **Indexes**: `managed_indexes` (regular, vector, text, TTL, compound)
364
+ - **Authentication**: `auth.policy`, `auth.users` (Casbin/OSO, demo users)
365
+ - **AI Services**: `embedding_config`, `memory_config`
366
+ - **Real-time**: `websockets` endpoints
367
+ - **CORS**: `cors` settings
368
+
369
+ **Start minimal, grow as needed.** You can begin with just `slug`, `name`, and `schema_version`, then add features incrementally.
370
+
371
+ **📖 Learn More:**
372
+ - [Quick Start Guide](docs/QUICK_START.md) - Get started with manifest.json
373
+ - [Manifest Deep Dive](docs/MANIFEST_DEEP_DIVE.md) - Comprehensive manifest.json guide
374
+ - [Examples](examples/) - Real-world manifest.json files
375
+
376
+ ---
377
+
303
378
  ## Links
304
379
 
305
380
  - [GitHub Repository](https://github.com/ranfysvalle02/mdb-engine)
306
381
  - [Documentation](https://github.com/ranfysvalle02/mdb-engine/tree/main/docs)
307
382
  - [All Examples](https://github.com/ranfysvalle02/mdb-engine/tree/main/examples)
308
- - [Quick Start Guide](https://github.com/ranfysvalle02/mdb-engine/blob/main/docs/QUICK_START.md)
309
- - [Contributing](https://github.com/ranfysvalle02/mdb-engine/blob/main/CONTRIBUTING.md)
383
+ - [Quick Start Guide](docs/QUICK_START.md) - **Start here!**
384
+ - [Contributing](CONTRIBUTING.md)
310
385
 
311
386
  ---
312
387
 
@@ -1,11 +1,11 @@
1
1
  mdb_engine/README.md,sha256=T3EFGcPopY9LslYW3lxgG3hohWkAOmBNbYG0FDMUJiY,3502
2
- mdb_engine/__init__.py,sha256=-W3Gdj2GAoptKsR_T4xluYnmnelZTdKrTxCthIytZ48,3008
2
+ mdb_engine/__init__.py,sha256=ll3Xc4FaoNqqK_lnWOJTyFHY3uAyoB40g3NnBjwyx5U,3155
3
3
  mdb_engine/config.py,sha256=DTAyxfKB8ogyI0v5QR9Y-SJOgXQr_eDBCKxNBSqEyLc,7269
4
4
  mdb_engine/constants.py,sha256=eaotvW57TVOg7rRbLziGrVNoP7adgw_G9iVByHezc_A,7837
5
5
  mdb_engine/dependencies.py,sha256=MJuYQhZ9ZGzXlip1ha5zba9Rvn04HDPWahJFJH81Q2s,14107
6
6
  mdb_engine/exceptions.py,sha256=NkBSdTBNP9bVTtI6w6mAoEfeVZDq-Bg7vCF2L26ZDZo,8442
7
7
  mdb_engine/auth/ARCHITECTURE.md,sha256=JXZsjEIpNz4Szk18KaOiEabhEuz1pmYWXQRN-EJEHDM,4076
8
- mdb_engine/auth/README.md,sha256=STL4PHyMlYpSNEAqo4RBKTEm4kz1GbWpI9c_lS94nV4,36802
8
+ mdb_engine/auth/README.md,sha256=IVlUOat96V3yM6wk4T-u4GxJ4-WF05eBSJBlvIexyBo,37285
9
9
  mdb_engine/auth/__init__.py,sha256=QemWqAVvqlxjF-UbzMTGP5AUOeuaAsUEtK4PMxmozmA,5852
10
10
  mdb_engine/auth/audit.py,sha256=UQ0Bj5Zxp5et9A21YZCVkUjaABFqO1CXaMrWxNcdxm8,17352
11
11
  mdb_engine/auth/base.py,sha256=4E3XkbruZLG9lc6aC56w0ypjnfiR5RbtjQKwn4am8to,7418
@@ -26,7 +26,7 @@ mdb_engine/auth/provider.py,sha256=FOSHn-jp4VYtxvmjnzho5kH6y-xDKWbcKUorYRRl1C4,2
26
26
  mdb_engine/auth/rate_limiter.py,sha256=l3EYZE1Kz9yVfZwNrKq_1AgdD7GXB1WOLSqqGQVSSgA,15808
27
27
  mdb_engine/auth/restrictions.py,sha256=tOyQBO_w0bK9zmTsOPZf9cbvh4oITvpNfSxIXt-XrcU,8824
28
28
  mdb_engine/auth/session_manager.py,sha256=ywWJjTarm-obgJ3zO3s-1cdqEYe0XrozlY00q_yMJ8I,15396
29
- mdb_engine/auth/shared_middleware.py,sha256=c1yQCbEWDyEH3Q0IieTO85Gin50GwTJnMEbwLBM5SHg,22312
29
+ mdb_engine/auth/shared_middleware.py,sha256=3lvm6aC0W_7ECvno_Mj3eu_93DZ--JiXhZ9hte8tvhM,30480
30
30
  mdb_engine/auth/shared_users.py,sha256=25OBks4VRHaYZW7R61vnplV7wmr7RRpDctSgnej_nxc,26773
31
31
  mdb_engine/auth/token_lifecycle.py,sha256=Q9S1X2Y6W7Ckt5PvyYXswBRh2Tg9DGpyRv_3Xve7VYQ,6708
32
32
  mdb_engine/auth/token_store.py,sha256=-B8j5RH5YEoKsswF4rnMoI51BaxMe4icke3kuehXmcI,9121
@@ -48,7 +48,7 @@ mdb_engine/core/connection.py,sha256=XnwuPG34pJ7kJGJ84T0mhj1UZ6_CLz_9qZf6NRYGIS8
48
48
  mdb_engine/core/encryption.py,sha256=RZ5LPF5g28E3ZBn6v1IMw_oas7u9YGFtBcEj8lTi9LM,7515
49
49
  mdb_engine/core/engine.py,sha256=ciQHxHEcFh-DOQ0X9gV5kKk9WAxj3GKg5JDIPfFZjMg,69459
50
50
  mdb_engine/core/index_management.py,sha256=9-r7MIy3JnjQ35sGqsbj8K_I07vAUWtAVgSWC99lJcE,5555
51
- mdb_engine/core/manifest.py,sha256=Rezktd0Ulv28N6vO2Pg5Z6HNVy8hEdQqJ5pO08rRk6U,133570
51
+ mdb_engine/core/manifest.py,sha256=ROaMKrlHY2gi77ScQCWu8U_QB7CVCoR8CQrP1gmtrtw,134756
52
52
  mdb_engine/core/ray_integration.py,sha256=vexYOzztscvRYje1xTNmXJbi99oJxCaVJAwKfTNTF_E,13610
53
53
  mdb_engine/core/seeding.py,sha256=c5IhdwlqUf_4Q5FFTAhPLaHPaUr_Txo3z_DUwZmWsFs,6421
54
54
  mdb_engine/core/service_initialization.py,sha256=rtb6BaPvFqomwT_s7bdbbvqi5m74llT0LkJFEhVG9Gg,12996
@@ -67,14 +67,14 @@ mdb_engine/di/scopes.py,sha256=pZgdkZ9ziW-vYCMvecC8Mv3Ud_Xk4ScsDYZ2eWHvar0,4165
67
67
  mdb_engine/embeddings/README.md,sha256=XjGWUXSdbSpXCAEEVfYmcJoFKBVmXDoM3eTjenrM5Z0,5926
68
68
  mdb_engine/embeddings/__init__.py,sha256=BM8tfcekVZv_iPQj3OuZBQ3hHr0eRQetNLEMysRTZkE,2129
69
69
  mdb_engine/embeddings/dependencies.py,sha256=0LIEU5L1jvZBKO4yhYxh4WxDhzJaZI9ohZGBNa6B7IY,2182
70
- mdb_engine/embeddings/service.py,sha256=yqVplODYLwWpEagv3mwS7n1-WXt2U-TluHwNi_BQ9Uc,25807
70
+ mdb_engine/embeddings/service.py,sha256=3JUqAU-e5TVLOpry5MdP-O4q6tHoqkXA8PyvcxqFoik,26983
71
71
  mdb_engine/indexes/README.md,sha256=r7duq-1vtqHhBk1cwoBMYYh_dfTzxiaQaPE3mLB_3JQ,15341
72
72
  mdb_engine/indexes/__init__.py,sha256=9QFJ6qo_yD26dZcKyKjj-hhesFpaomBt-mWTtYTQvqc,613
73
73
  mdb_engine/indexes/helpers.py,sha256=tJHqDm18jKLrW-P2ofmnUnaf4_-V5xDLjqP_WU8W9MM,4190
74
74
  mdb_engine/indexes/manager.py,sha256=XSjvFNMOv67yey5Vi4mKBt6_w4b6Hqtv24fiAXnfLi0,32460
75
- mdb_engine/memory/README.md,sha256=vy2FSXADcqG18YrFBfrMph9a1vYKuLijhs8ziNFdvRk,10631
75
+ mdb_engine/memory/README.md,sha256=uOE4SnPyq8TdoxGrttof5fSj2KSqnrgzUorMCV_1wg0,13624
76
76
  mdb_engine/memory/__init__.py,sha256=e4kAYgxd_-WAH8GovTwjEBO9hvASu_kXEupMgksAL-U,1008
77
- mdb_engine/memory/service.py,sha256=zX0oaHs8SHikH1fX4CtRF5pbOu1swEoiy3Segz_nLZI,47461
77
+ mdb_engine/memory/service.py,sha256=l2bkKVN9AyUjO9K9ykb5BK9dZjs3ns78FJLOD5LajsY,18454
78
78
  mdb_engine/observability/README.md,sha256=CMgQaC1H8ESmCitfbhJifz6-XoXH_FPNE4MvuZ-oFas,13085
79
79
  mdb_engine/observability/__init__.py,sha256=jjLsrW6Gy2ayrbfLrgHsDB61NxWWkYLHwv0q-N3fxjA,1213
80
80
  mdb_engine/observability/health.py,sha256=eFd8a-Rv3NWML0EDdZ8thZWTiqP_FUZbub97hV2z57g,9190
@@ -87,10 +87,11 @@ mdb_engine/repositories/unit_of_work.py,sha256=XvmwGOspEDj4hsfOULPsQKjB1QZqh83TJ
87
87
  mdb_engine/routing/README.md,sha256=WVvTQXDq0amryrjkCu0wP_piOEwFjLukjmPz2mroWHY,13658
88
88
  mdb_engine/routing/__init__.py,sha256=reupjHi_RTc2ZBA4AH5XzobAmqy4EQIsfSUcTkFknUM,2438
89
89
  mdb_engine/routing/websockets.py,sha256=3X4OjQv_Nln4UmeifJky0gFhMG8A6alR77I8g1iIOLY,29311
90
- mdb_engine/utils/__init__.py,sha256=_xjHB5p6WLWBql1DyDqf5zdjj2xpfMlK25Y6BH9-oFk,145
91
- mdb_engine-0.2.3.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
92
- mdb_engine-0.2.3.dist-info/METADATA,sha256=-GUB0bt3MSLlo3Ayigjb2NnA2rZBPtdXrgq7oI0gBEE,10490
93
- mdb_engine-0.2.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
94
- mdb_engine-0.2.3.dist-info/entry_points.txt,sha256=INCbYdFbBzJalwPwxliEzLmPfR57IvQ7RAXG_pn8cL8,48
95
- mdb_engine-0.2.3.dist-info/top_level.txt,sha256=PH0UEBwTtgkm2vWvC9He_EOMn7hVn_Wg_Jyc0SmeO8k,11
96
- mdb_engine-0.2.3.dist-info/RECORD,,
90
+ mdb_engine/utils/__init__.py,sha256=lDxQSGqkV4fVw5TWIk6FA6_eey_ZnEtMY0fir3cpAe8,236
91
+ mdb_engine/utils/mongo.py,sha256=Oqtv4tQdpiiZzrilGLEYQPo8Vmh8WsTQypxQs8Of53s,3369
92
+ mdb_engine-0.2.4.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
93
+ mdb_engine-0.2.4.dist-info/METADATA,sha256=DRYO0436-KCFjF-HHi1deGWWoO0Yq3vzKl53qow2ldE,12750
94
+ mdb_engine-0.2.4.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
95
+ mdb_engine-0.2.4.dist-info/entry_points.txt,sha256=INCbYdFbBzJalwPwxliEzLmPfR57IvQ7RAXG_pn8cL8,48
96
+ mdb_engine-0.2.4.dist-info/top_level.txt,sha256=PH0UEBwTtgkm2vWvC9He_EOMn7hVn_Wg_Jyc0SmeO8k,11
97
+ mdb_engine-0.2.4.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5