surreal-orm-lite 0.3.0__tar.gz → 0.5.0__tar.gz

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.
Files changed (24) hide show
  1. {surreal_orm_lite-0.3.0 → surreal_orm_lite-0.5.0}/CHANGELOG.md +66 -0
  2. surreal_orm_lite-0.5.0/PKG-INFO +451 -0
  3. surreal_orm_lite-0.5.0/README.md +401 -0
  4. {surreal_orm_lite-0.3.0 → surreal_orm_lite-0.5.0}/pyproject.toml +2 -2
  5. {surreal_orm_lite-0.3.0 → surreal_orm_lite-0.5.0}/src/surreal_orm_lite/__init__.py +28 -1
  6. {surreal_orm_lite-0.3.0 → surreal_orm_lite-0.5.0}/src/surreal_orm_lite/constants.py +4 -0
  7. {surreal_orm_lite-0.3.0 → surreal_orm_lite-0.5.0}/src/surreal_orm_lite/model_base.py +101 -14
  8. surreal_orm_lite-0.5.0/src/surreal_orm_lite/q.py +112 -0
  9. surreal_orm_lite-0.5.0/src/surreal_orm_lite/query_set.py +688 -0
  10. surreal_orm_lite-0.5.0/src/surreal_orm_lite/signals.py +286 -0
  11. surreal_orm_lite-0.5.0/src/surreal_orm_lite/utils.py +114 -0
  12. surreal_orm_lite-0.3.0/PKG-INFO +0 -283
  13. surreal_orm_lite-0.3.0/README.md +0 -233
  14. surreal_orm_lite-0.3.0/src/surreal_orm_lite/query_set.py +0 -870
  15. surreal_orm_lite-0.3.0/src/surreal_orm_lite/utils.py +0 -53
  16. {surreal_orm_lite-0.3.0 → surreal_orm_lite-0.5.0}/.gitignore +0 -0
  17. {surreal_orm_lite-0.3.0 → surreal_orm_lite-0.5.0}/LICENSE +0 -0
  18. {surreal_orm_lite-0.3.0 → surreal_orm_lite-0.5.0}/Makefile +0 -0
  19. {surreal_orm_lite-0.3.0 → surreal_orm_lite-0.5.0}/src/__init__.py +0 -0
  20. {surreal_orm_lite-0.3.0 → surreal_orm_lite-0.5.0}/src/surreal_orm_lite/aggregations.py +0 -0
  21. {surreal_orm_lite-0.3.0 → surreal_orm_lite-0.5.0}/src/surreal_orm_lite/connection_manager.py +0 -0
  22. {surreal_orm_lite-0.3.0 → surreal_orm_lite-0.5.0}/src/surreal_orm_lite/enum.py +0 -0
  23. {surreal_orm_lite-0.3.0 → surreal_orm_lite-0.5.0}/src/surreal_orm_lite/exceptions.py +0 -0
  24. {surreal_orm_lite-0.3.0 → surreal_orm_lite-0.5.0}/src/surreal_orm_lite/py.typed +0 -0
@@ -5,6 +5,72 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.5.0] - 2026-02-11
9
+
10
+ ### Added
11
+
12
+ - **Q Objects**: Django-style composable query expressions for complex filters
13
+ - `Q(field=value)` for basic conditions
14
+ - `Q(...) | Q(...)` for OR queries
15
+ - `Q(...) & Q(...)` for AND queries
16
+ - `~Q(...)` for NOT queries
17
+ - Nested combinations: `Q(age__gte=18) & (Q(role="admin") | Q(role="mod"))`
18
+
19
+ - **Parameterized Filters**: All filter values now use parameterized variables (`$_fN`) instead of string interpolation, preventing SQL injection
20
+
21
+ - **New Lookup Operators**:
22
+ - `not_in` - NOT IN operator
23
+ - `not_contains` - CONTAINSNOT operator
24
+ - `containsall` - CONTAINSALL operator
25
+ - `containsany` - CONTAINSANY operator
26
+
27
+ - **`-field` Ordering Shorthand**: Prefix field with `-` for descending order
28
+ - `order_by("-created_at")` instead of `order_by("created_at", OrderBy.DESC)`
29
+ - Multi-field ordering: `order_by("-age", "name")`
30
+
31
+ - **Bulk Operations**:
32
+ - `bulk_create(models)` - Create multiple records via SDK's `insert()`
33
+ - `bulk_update(**kwargs)` - Update all matching records with parameterized SET clause
34
+ - `bulk_delete()` - Delete all matching records, returns count
35
+
36
+ - New `Q` class exported from `surreal_orm_lite`
37
+ - New test file `tests/test_v050.py` for all v0.5.0 features
38
+
39
+ ### Changed
40
+
41
+ - `_compile_query()`, `_compile_aggregation_query()`, `_compile_group_by_query()` now return `tuple[str, dict]` with parameterized variables
42
+ - `_execute_query()` now accepts optional `variables` parameter
43
+ - `filter()` now accepts `*args: Q` positional arguments alongside keyword filters
44
+ - `order_by()` now accepts multiple fields with `-field` prefix support
45
+ - `_build_where()` replaces `_build_where_clauses()` and returns parameterized WHERE clause
46
+ - Shared `parse_lookup()` and `build_filter_condition()` functions moved to `utils.py`
47
+ - Fixed `isnull` lookup: now correctly generates `IS NULL`/`IS NOT NULL`
48
+
49
+ ## [0.4.0] - 2026-02-07
50
+
51
+ ### Added
52
+
53
+ - **Model Signals**: Django-style event system for model lifecycle
54
+ - `Signal` class for pre/post event handlers
55
+ - `AroundSignal` class for context manager-style wrapping signals with `yield`
56
+ - `pre_save` / `post_save` - Fired before/after `save()` operations
57
+ - `pre_update` / `post_update` - Fired before/after `update()` and `merge()` operations
58
+ - `pre_delete` / `post_delete` - Fired before/after `delete()` operations
59
+ - `around_save` / `around_update` / `around_delete` - Wrap operations for timing, logging, etc.
60
+ - `connect(model_class)` decorator for registering handlers
61
+ - `disconnect(handler, model_class)` for removing handlers
62
+ - `clear()` for removing all handlers
63
+ - `has_handlers()` for checking if handlers are registered
64
+
65
+ - `post_save` signal includes `created` flag to distinguish new records
66
+ - `pre_update` / `post_update` signals include `update_fields` list
67
+ - New test file `tests/test_signals.py` with unit and e2e tests
68
+
69
+ ### Changed
70
+
71
+ - `save()`, `update()`, `merge()`, `delete()` now emit signals when handlers are registered
72
+ - Internal `_do_save()` method extracted from `save()` for signal integration
73
+
8
74
  ## [0.3.0] - 2026-02-05
9
75
 
10
76
  ### Added
@@ -0,0 +1,451 @@
1
+ Metadata-Version: 2.4
2
+ Name: surreal-orm-lite
3
+ Version: 0.5.0
4
+ Summary: Lightweight Django-style ORM for SurrealDB using the official Python SDK. Async support with Pydantic validation.
5
+ Project-URL: Homepage, https://github.com/EulogySnowfall/SurrealDB-ORM-lite
6
+ Project-URL: Documentation, https://github.com/EulogySnowfall/SurrealDB-ORM-lite
7
+ Project-URL: Repository, https://github.com/EulogySnowfall/SurrealDB-ORM-lite.git
8
+ Project-URL: Issues, https://github.com/EulogySnowfall/SurrealDB-ORM-lite/issues
9
+ Project-URL: Changelog, https://github.com/EulogySnowfall/SurrealDB-ORM-lite/blob/main/CHANGELOG.md
10
+ Author-email: Yannick Croteau <croteau.yannick@gmail.com>
11
+ License: # MIT License
12
+
13
+ Copyright (c) 2024-2026 Yannick Croteau
14
+
15
+ Permission is hereby granted, free of charge, to any person obtaining a copy
16
+ of this software and associated documentation files (the "Software"), to deal
17
+ in the Software without restriction, including without limitation the rights
18
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19
+ copies of the Software, and to permit persons to whom the Software is
20
+ furnished to do so, subject to the following conditions:
21
+
22
+ The above copyright notice and this permission notice shall be included in all
23
+ copies or substantial portions of the Software.
24
+
25
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
+ SOFTWARE.
32
+ License-File: LICENSE
33
+ Keywords: async,database,orm,pydantic,surrealdb
34
+ Classifier: Development Status :: 3 - Alpha
35
+ Classifier: Framework :: Pydantic :: 2
36
+ Classifier: License :: OSI Approved :: MIT License
37
+ Classifier: Operating System :: OS Independent
38
+ Classifier: Programming Language :: Python :: 3
39
+ Classifier: Programming Language :: Python :: 3.11
40
+ Classifier: Programming Language :: Python :: 3.12
41
+ Classifier: Programming Language :: Python :: 3.13
42
+ Classifier: Programming Language :: Python :: 3.14
43
+ Classifier: Topic :: Database
44
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
45
+ Classifier: Typing :: Typed
46
+ Requires-Python: >=3.11
47
+ Requires-Dist: pydantic>=2.12.5
48
+ Requires-Dist: surrealdb>=1.0.8
49
+ Description-Content-Type: text/markdown
50
+
51
+ # Surreal ORM Lite
52
+
53
+ ![Python](https://img.shields.io/badge/python-3.11%2B-blue)
54
+ ![SurrealDB](https://img.shields.io/badge/SurrealDB-2.6.0-purple)
55
+ ![SDK](https://img.shields.io/badge/SDK-Official%201.0.8-green)
56
+ ![License](https://img.shields.io/badge/license-MIT-blue)
57
+ [![codecov](https://codecov.io/gh/EulogySnowfall/SurrealDB-ORM-lite/graph/badge.svg)](https://codecov.io/gh/EulogySnowfall/SurrealDB-ORM-lite)
58
+
59
+ **Surreal ORM Lite** is a lightweight, Django-style ORM for [SurrealDB](https://surrealdb.com/) that uses the **official SurrealDB Python SDK**. It provides a simple and intuitive interface for database operations with full async support and Pydantic validation.
60
+
61
+ ## Why This Project?
62
+
63
+ This ORM is designed to:
64
+
65
+ - Use the **official SurrealDB SDK** (`surrealdb>=1.0.8`) for maximum compatibility
66
+ - Stay **lightweight** with minimal dependencies
67
+ - Keep **up-to-date** with SurrealDB and SDK releases
68
+ - Provide **Django-style** query syntax that developers love
69
+
70
+ ---
71
+
72
+ ## Requirements
73
+
74
+ | Dependency | Version |
75
+ | ------------ | ---------------- |
76
+ | Python | 3.11+ |
77
+ | SurrealDB | 2.6.0+ |
78
+ | Official SDK | surrealdb>=1.0.8 |
79
+ | Pydantic | >=2.12.5 |
80
+
81
+ ---
82
+
83
+ ## Installation
84
+
85
+ ```bash
86
+ pip install surreal-orm-lite
87
+ ```
88
+
89
+ Or with uv:
90
+
91
+ ```bash
92
+ uv add surreal-orm-lite
93
+ ```
94
+
95
+ ---
96
+
97
+ ## Quick Start
98
+
99
+ ### 1. Configure the Connection
100
+
101
+ ```python
102
+ from surreal_orm_lite import SurrealDBConnectionManager
103
+
104
+ SurrealDBConnectionManager.set_connection(
105
+ url="http://localhost:8000",
106
+ user="root",
107
+ password="root",
108
+ namespace="my_namespace",
109
+ database="my_database",
110
+ )
111
+ ```
112
+
113
+ ### 2. Define a Model
114
+
115
+ ```python
116
+ from surreal_orm_lite import BaseSurrealModel
117
+ from pydantic import Field
118
+
119
+ class User(BaseSurrealModel):
120
+ id: str | None = None
121
+ name: str = Field(..., max_length=100)
122
+ email: str
123
+ age: int = Field(..., ge=0)
124
+ ```
125
+
126
+ ### 3. CRUD Operations
127
+
128
+ ```python
129
+ # Create
130
+ user = User(name="Alice", email="alice@example.com", age=30)
131
+ await user.save()
132
+
133
+ # Read
134
+ user = await User.objects().get("alice_id")
135
+ users = await User.objects().filter(age__gte=18).exec()
136
+
137
+ # Update
138
+ user.age = 31
139
+ await user.update()
140
+
141
+ # Or partial update
142
+ await user.merge(age=31)
143
+
144
+ # Delete
145
+ await user.delete()
146
+ ```
147
+
148
+ ### 4. QuerySet Methods
149
+
150
+ ```python
151
+ # Filter with Django-style lookups
152
+ users = await User.objects().filter(
153
+ age__gte=18,
154
+ name__startswith="A"
155
+ ).exec()
156
+
157
+ # Ordering (with -field shorthand for DESC)
158
+ users = await User.objects().order_by("name").exec()
159
+ users = await User.objects().order_by("-age", "name").exec()
160
+
161
+ # Pagination
162
+ users = await User.objects().limit(10).offset(20).exec()
163
+
164
+ # Select specific fields
165
+ results = await User.objects().select("name", "email").exec()
166
+
167
+ # Get first result
168
+ user = await User.objects().filter(name="Alice").first()
169
+
170
+ # Get all records
171
+ all_users = await User.objects().all()
172
+
173
+ # Custom query
174
+ results = await User.objects().query(
175
+ "SELECT * FROM User WHERE age > $min_age",
176
+ {"min_age": 21}
177
+ )
178
+ ```
179
+
180
+ ---
181
+
182
+ ## Features
183
+
184
+ | Feature | Status |
185
+ | ---------------------- | ------ |
186
+ | Async/await support | ✅ |
187
+ | Pydantic validation | ✅ |
188
+ | CRUD operations | ✅ |
189
+ | QuerySet with filters | ✅ |
190
+ | Django-style lookups | ✅ |
191
+ | Custom primary keys | ✅ |
192
+ | HTTP connections | ✅ |
193
+ | WebSocket connections | ✅ |
194
+ | Aggregations | ✅ |
195
+ | GROUP BY | ✅ |
196
+ | Model Signals | ✅ |
197
+ | Raw SurrealQL queries | ✅ |
198
+ | Q Objects (OR/AND/NOT) | ✅ |
199
+ | Parameterized filters | ✅ |
200
+ | Bulk operations | ✅ |
201
+ | `-field` ordering | ✅ |
202
+
203
+ ### Supported Filter Lookups
204
+
205
+ - `exact` (default)
206
+ - `gt`, `gte`, `lt`, `lte`
207
+ - `in`, `not_in`
208
+ - `contains`, `icontains`, `not_contains`
209
+ - `containsall`, `containsany`
210
+ - `startswith`, `istartswith`
211
+ - `endswith`, `iendswith`
212
+ - `like`, `ilike`
213
+ - `match`, `regex`, `iregex`
214
+ - `isnull`
215
+
216
+ ### 5. Q Objects (Complex Queries)
217
+
218
+ ```python
219
+ from surreal_orm_lite import Q
220
+
221
+ # OR queries
222
+ users = await User.objects().filter(Q(name="Alice") | Q(name="Bob")).exec()
223
+
224
+ # NOT queries
225
+ active = await User.objects().filter(~Q(status="banned")).exec()
226
+
227
+ # Complex combinations
228
+ results = await User.objects().filter(
229
+ Q(age__gte=18) & (Q(role="admin") | Q(role="mod"))
230
+ ).exec()
231
+
232
+ # Mix Q objects with keyword filters
233
+ results = await User.objects().filter(
234
+ Q(role="admin") | Q(role="mod"),
235
+ age__gte=25
236
+ ).exec()
237
+ ```
238
+
239
+ ### 6. Bulk Operations
240
+
241
+ ```python
242
+ # Bulk create
243
+ users = [User(name="Alice", age=30), User(name="Bob", age=25)]
244
+ created = await User.objects().bulk_create(users)
245
+
246
+ # Bulk update (returns count of updated records)
247
+ count = await User.objects().filter(status="pending").bulk_update(status="active")
248
+
249
+ # Bulk delete (returns count of deleted records)
250
+ count = await User.objects().filter(status="inactive").bulk_delete()
251
+ ```
252
+
253
+ ### 7. Aggregations
254
+
255
+ ```python
256
+ from surreal_orm_lite import Count, Sum, Avg, Min, Max
257
+
258
+ # Simple aggregations
259
+ count = await User.objects().count()
260
+ total = await Order.objects().sum("amount")
261
+ avg_age = await User.objects().avg("age")
262
+ max_price = await Product.objects().max("price")
263
+ min_price = await Product.objects().min("price")
264
+
265
+ # Check existence
266
+ has_admins = await User.objects().filter(role="admin").exists()
267
+
268
+ # GROUP BY with annotations
269
+ results = await User.objects().values("status").annotate(count=Count()).exec()
270
+ # [{"status": "active", "count": 42}, {"status": "inactive", "count": 8}]
271
+
272
+ # Raw SurrealQL queries
273
+ results = await User.raw_query(
274
+ "SELECT * FROM User WHERE age > $min_age",
275
+ variables={"min_age": 18}
276
+ )
277
+ ```
278
+
279
+ ### 8. Model Signals
280
+
281
+ ```python
282
+ from surreal_orm_lite import pre_save, post_save, pre_delete, post_delete
283
+
284
+ @post_save.connect(User)
285
+ async def on_user_saved(sender, instance, created, **kwargs):
286
+ """Called after every User save."""
287
+ if created:
288
+ await send_welcome_email(instance.email)
289
+ await invalidate_cache(f"user:{instance.id}")
290
+
291
+ @pre_delete.connect(User)
292
+ async def on_user_deleting(sender, instance, **kwargs):
293
+ """Called before User deletion."""
294
+ await archive_user_data(instance.id)
295
+ ```
296
+
297
+ **Available signals:**
298
+
299
+ | Signal | When | Extra kwargs |
300
+ | --------------- | --------------------------- | --------------- |
301
+ | `pre_save` | Before `save()` | |
302
+ | `post_save` | After `save()` | `created` |
303
+ | `pre_update` | Before `update()`/`merge()` | `update_fields` |
304
+ | `post_update` | After `update()`/`merge()` | `update_fields` |
305
+ | `pre_delete` | Before `delete()` | |
306
+ | `post_delete` | After `delete()` | |
307
+ | `around_save` | Wraps `save()` | |
308
+ | `around_update` | Wraps `update()`/`merge()` | `update_fields` |
309
+ | `around_delete` | Wraps `delete()` | |
310
+
311
+ **Around signals** use async generators to wrap operations:
312
+
313
+ ```python
314
+ from surreal_orm_lite import around_save
315
+
316
+ @around_save.connect(User)
317
+ async def time_user_save(sender, instance, **kwargs):
318
+ import time
319
+ start = time.time()
320
+ yield # save() executes here
321
+ duration = time.time() - start
322
+ print(f"Save took {duration:.3f}s")
323
+ ```
324
+
325
+ ---
326
+
327
+ ## Configuration Options
328
+
329
+ ### Custom Primary Key
330
+
331
+ ```python
332
+ from surreal_orm_lite import BaseSurrealModel, SurrealConfigDict
333
+
334
+ class Product(BaseSurrealModel):
335
+ model_config = SurrealConfigDict(primary_key="sku")
336
+
337
+ sku: str
338
+ name: str
339
+ price: float
340
+ ```
341
+
342
+ ### Context Manager
343
+
344
+ ```python
345
+ async with SurrealDBConnectionManager():
346
+ users = await User.objects().all()
347
+ # Connection automatically closed
348
+ ```
349
+
350
+ ---
351
+
352
+ ## Compatibility
353
+
354
+ This ORM is tested and compatible with:
355
+
356
+ | SurrealDB Version | SDK Version | Status |
357
+ | ----------------- | ----------- | ------------- |
358
+ | 2.6.0 | 1.0.8 | ✅ Tested |
359
+ | 2.5.x | 1.0.8 | ✅ Compatible |
360
+
361
+ ---
362
+
363
+ ## Contributing
364
+
365
+ Contributions are welcome! Please:
366
+
367
+ 1. Fork the repository
368
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
369
+ 3. Commit your changes (`git commit -m "Add amazing feature"`)
370
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
371
+ 5. Open a Pull Request
372
+
373
+ ---
374
+
375
+ ## Roadmap
376
+
377
+ | Version | Theme | Status |
378
+ | ------- | ----------------------------- | ----------- |
379
+ | v0.2.x | Core ORM (CRUD, QuerySet) | ✅ Released |
380
+ | v0.3.0 | Aggregations & Utilities | ✅ Released |
381
+ | v0.4.0 | Model Signals | ✅ Released |
382
+ | v0.5.0 | Bulk Operations & Q Objects | ✅ Released |
383
+ | v0.6.0 | Relations & Graph | 📋 Next |
384
+ | v0.7.0 | Transactions ORM | 📋 Planned |
385
+ | v0.8.0 | SurrealFunc & Computed Fields | 📋 Planned |
386
+ | v0.9.0 | Field Aliases & DX | 📋 Planned |
387
+ | v1.0.0 | Production Ready | 📋 Planned |
388
+
389
+ See [docs/ROADMAP.md](docs/ROADMAP.md) for full details.
390
+
391
+ ---
392
+
393
+ ## SurrealDB-ORM-lite vs SurrealDB-ORM
394
+
395
+ This project prioritizes **stability and compatibility** with the official SurrealDB Python SDK. The full [SurrealDB-ORM](https://github.com/EulogySnowfall/SurrealDB-ORM/) uses a custom SDK for advanced features.
396
+
397
+ | Feature | ORM-lite (official SDK) | ORM (custom SDK) |
398
+ | ------------------------- | ----------------------- | ---------------- |
399
+ | CRUD & QuerySet | ✅ | ✅ |
400
+ | Aggregations & GROUP BY | ✅ | ✅ |
401
+ | Model Signals | ✅ | ✅ |
402
+ | Bulk Operations | ✅ | ✅ |
403
+ | Q Objects (OR/AND/NOT) | ✅ | ✅ |
404
+ | Parameterized Filters | ✅ | ✅ |
405
+ | Relations & Graph | v0.6.0 | ✅ |
406
+ | FETCH clause | v0.6.0 | ✅ |
407
+ | Transactions (tx=) | v0.7.0 | ✅ |
408
+ | SurrealFunc & Computed | v0.8.0 | ✅ |
409
+ | Field Aliases | v0.9.0 | ✅ |
410
+ | Retry, Logging, Metrics | v0.10.0 | ✅ |
411
+ | Live Models / CDC | ❌ | ✅ |
412
+ | Vector / Full-Text Search | ❌ | ✅ |
413
+ | Hybrid Search (RRF) | ❌ | ✅ |
414
+ | Migrations & CLI | ❌ | ✅ |
415
+ | JWT Authentication | ❌ | ✅ |
416
+ | Schema Introspection | ❌ | ✅ |
417
+ | Connection Pool | ❌ | ✅ |
418
+ | CBOR Protocol | ❌ | ✅ |
419
+ | Subqueries & Query Cache | ❌ | ✅ |
420
+ | Geospatial Fields | ❌ | ✅ |
421
+ | DEFINE EVENT | ❌ | ✅ |
422
+ | Test Fixtures & Factories | ❌ | ✅ |
423
+ | Atomic Array Operations | ❌ | ✅ |
424
+
425
+ **Choose ORM-lite** if you want the official SDK, minimal dependencies, and core ORM features.
426
+
427
+ **Choose ORM** if you need live queries, migrations, authentication, vector search, or advanced features.
428
+
429
+ - **SurrealDB-ORM GitHub**: [github.com/EulogySnowfall/SurrealDB-ORM](https://github.com/EulogySnowfall/SurrealDB-ORM/)
430
+ - **SurrealDB-ORM PyPI**: [surrealdb-orm](https://pypi.org/project/surrealdb-orm/)
431
+
432
+ ---
433
+
434
+ ## License
435
+
436
+ MIT License - see [LICENSE](LICENSE) for details.
437
+
438
+ ---
439
+
440
+ ## Author
441
+
442
+ **Yannick Croteau**
443
+ GitHub: [@EulogySnowfall](https://github.com/EulogySnowfall)
444
+
445
+ ---
446
+
447
+ ## Related Projects
448
+
449
+ - [SurrealDB](https://surrealdb.com/) - The database
450
+ - [surrealdb.py](https://github.com/surrealdb/surrealdb.py) - Official Python SDK
451
+ - [SurrealDB-ORM](https://github.com/EulogySnowfall/SurrealDB-ORM/) - Full-featured ORM with custom SDK