An async-first Python library for building graph-based spatial applications with FastAPI integration. Provides entity-centric database operations with automatic context management.
- Overview
- Key Features
- Installation
- Quick Start
- Core Concepts
- Configuration
- Documentation
- Contributing
- License
jvspatial is an async-first Python library for building graph-based spatial applications with FastAPI integration. It provides entity-centric database operations with automatic context management.
Inspired by Jaseci's object-spatial paradigm and leveraging Python's async capabilities, jvspatial empowers developers to model complex relationships, traverse object graphs, and implement agent-based architectures that scale with modern cloud-native concurrency requirements.
Key Design Principles:
- Hierarchy: Object → Node → Edge/Walker inheritance
- Entity-Centric: Direct database operations via entity methods
- Unified Decorators:
@attributefor entity attributes,@endpointfor API endpoints - Automatic Context: Server automatically provides database context to entities
- Essential CRUD: Core database operations with pagination support
- Unified Configuration: Single
Configclass for all settings - Async-First: Built for modern Python async/await patterns
- Object: Base class for all entities
- Node: Graph nodes with spatial data (inherits from Object)
- Edge: Relationships between nodes (inherits from Object)
- Walker: Graph traversal and pathfinding (inherits from Object)
- Root: Singleton root node (inherits from Node)
@attribute- Define entity attributes with protection, transient flags, and validation@endpoint- Unified endpoint decorator for both functions and Walker classes- Automatic parameter and response schema generation
- Entity methods:
Entity.get(),Entity.find(),Entity.create(),entity.save(),entity.delete() - Automatic context management
- Support for JSON, SQLite, MongoDB, and DynamoDB backends
- Multi-database support with prime database for core persistence
- Custom database registration for extensibility
- Pagination with
ObjectPager
- Single
Configclass for all settings - Environment variable support
- Type-safe configuration
- Built-in FastAPI server with automatic OpenAPI documentation
- Automatic endpoint registration from decorators
- Authentication and authorization with automatic endpoint registration when enabled
- Response schema definitions with examples
- Entity-centric CRUD operations
- DeferredSaveMixin: Batch multiple
save()calls into a single database write - Configurable via
JVSPATIAL_ENABLE_DEFERRED_SAVESenvironment variable - Ideal for entities with rapid, sequential updates
# Core installation
pip install jvspatial💡 Standard Examples: For production-ready API implementations, see:
- Authenticated API:
examples/api/authenticated_endpoints_example.py- Complete CRUD with authentication- Unauthenticated API:
examples/api/unauthenticated_endpoints_example.py- Public read-only API
from jvspatial.api import Server, endpoint
from jvspatial.core import Node
# Create server (entity-centric operations available automatically)
server = Server(
title="My API",
db_type="json",
db_path="./jvdb",
auth_enabled=False # Set to True to enable authentication
)
# Define entity
class User(Node):
name: str = ""
email: str = ""
# Create endpoint
@endpoint("/users/{user_id}", methods=["GET"])
async def get_user(user_id: str):
user = await User.get(user_id)
if not user:
from fastapi import HTTPException
raise HTTPException(status_code=404, detail="User not found")
return {"user": await user.export()}
if __name__ == "__main__":
server.run()from jvspatial.core import Node
from jvspatial.core.annotations import attribute
class User(Node):
name: str = ""
email: str = ""
cache: dict = attribute(transient=True, default_factory=dict)The @endpoint decorator works with both functions and Walker classes:
from jvspatial.api import Server, endpoint
from jvspatial.core import Node
server = Server(title="My API", db_type="json", db_path="./jvdb")
# Function endpoint
@endpoint("/api/users", methods=["GET"])
async def list_users(page: int = 1, per_page: int = 10):
from jvspatial.core.pager import ObjectPager
pager = ObjectPager(User, page_size=per_page)
users = await pager.get_page(page=page)
import asyncio
users_list = await asyncio.gather(*[user.export() for user in users])
return {"users": users_list}
# Authenticated endpoint
@endpoint("/api/admin", methods=["GET"], auth=True, roles=["admin"])
async def admin_panel():
return {"admin": "dashboard"}
# Endpoint with response schema
from jvspatial.api.endpoints.response import ResponseField, success_response
@endpoint(
"/api/users",
methods=["GET"],
response=success_response(
data={
"users": ResponseField(List[Dict], "List of users"),
"total": ResponseField(int, "Total count")
}
)
)
async def get_users():
return {"users": [], "total": 0}from jvspatial.core import Node
class User(Node):
name: str = ""
email: str = ""
# Entity-centric operations (no context needed - server provides it automatically)
user = await User.create(name="John", email="john@example.com")
users = await User.find({"context.name": "John"}) # Use context. prefix for fields
user = await User.get(user_id) # Returns None if not found
if user:
await user.save()
await user.delete()
# Efficient counting
total_users = await User.count() # Count all users
active_users = await User.count({"context.active": True}) # Count filtered users using query dict
active_users = await User.count(active=True) # Count filtered users using keyword argumentsfrom jvspatial.api import Server
# Basic server
server = Server(
title="My API",
description="API description",
version="1.0.0",
db_type="json",
db_path="./jvdb"
)
# Server with authentication
server = Server(
title="Secure API",
auth_enabled=True, # Automatically registers /auth/register, /auth/login, /auth/logout
jwt_auth_enabled=True,
jwt_secret="your-secret-key",
jwt_expire_minutes=60,
db_type="json",
db_path="./jvdb"
)
# Server without authentication (public API)
server = Server(
title="Public API",
auth_enabled=False, # NO authentication endpoints registered
db_type="json",
db_path="./jvdb_public"
)auth_enabled=True: Server automatically registers authentication endpoints (/auth/register,/auth/login,/auth/logout)auth_enabled=False: Authentication endpoints are NOT registered (public API)
- Quick Start Guide - Get started in 5 minutes
- Examples - Standard implementation examples ⭐
- Authenticated API Example - Complete CRUD with authentication
- Unauthenticated API Example - Public read-only API
- API Implementation Standards - Standard patterns and best practices
- REST API Guide - API design patterns
- Server API Guide - Server configuration
- Authentication Guide - Authentication patterns
- Entity Reference - Node, Edge, Walker classes
- API Architecture - System architecture
- Graph Context Guide - Context management and multi-database support
- Custom Database Guide - Implementing custom database backends
- Graph Visualization - Export graphs in DOT/Mermaid formats
- Pagination - ObjectPager usage
We welcome contributions! Please see our Contributing Guide for details.
This project is licensed under the MIT License - see the LICENSE file for details.