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: Pydantic
ServerConfigmerged atServerstartup (constructor kwargs /configdict override allowlistedJVSPATIAL_*env, which override library defaults) - 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
- Canonical
ServerConfig(Pydantic) for all server settings - Allowlisted
JVSPATIAL_*env vars merged before explicitServer(...)/config=overrides - Unknown or removed
JVSPATIAL_*keys are rejected (seedocs/md/environment-configuration.md)
- 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_SAVES; disabled automatically in serverless mode (deferred_saves_globally_allowed()) - Ideal for entities with rapid, sequential updates
# Core installation
pip install jvspatialStandard 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
fromjvspatial.apiimportServer, endpointfromjvspatial.coreimportNode# Create server (entity-centric operations available automatically)server=Server(
title="My API",
db_type="json",
db_path="./jvdb",
auth=dict(auth_enabled=False) # Set auth_enabled=True for authentication
)
# Define entityclassUser(Node):
name: str=""email: str=""# Create endpoint@endpoint("/users/{user_id}", methods=["GET"])asyncdefget_user(user_id: str):
user=awaitUser.get(user_id)
ifnotuser:
fromfastapiimportHTTPExceptionraiseHTTPException(status_code=404, detail="User not found")
return {"user": awaituser.export()}
if__name__=="__main__":
server.run()fromjvspatial.coreimportNodefromjvspatial.core.annotationsimportattributeclassUser(Node):
name: str=""email: str=""cache: dict=attribute(transient=True, default_factory=dict)The @endpoint decorator works with both functions and Walker classes:
fromjvspatial.apiimportServer, endpointfromjvspatial.coreimportNodeserver=Server(title="My API", db_type="json", db_path="./jvdb")
# Function endpoint@endpoint("/api/users", methods=["GET"])asyncdeflist_users(page: int=1, per_page: int=10):
fromjvspatial.core.pagerimportObjectPagerpager=ObjectPager(User, page_size=per_page)
users=awaitpager.get_page(page=page)
importasynciousers_list=awaitasyncio.gather(*[user.export() foruserinusers])
return {"users": users_list}
# Authenticated endpoint@endpoint("/api/admin", methods=["GET"], auth=True, roles=["admin"])asyncdefadmin_panel():
return {"admin": "dashboard"}
# Endpoint with response schemafromjvspatial.api.endpoints.responseimportResponseField, success_response@endpoint("/api/users",methods=["GET"],response=success_response(data={"users": ResponseField(List[Dict], "List of users"),"total": ResponseField(int, "Total count") } ))asyncdefget_users():
return {"users": [], "total": 0}fromjvspatial.coreimportNodeclassUser(Node):
name: str=""email: str=""# Entity-centric operations (no context needed - server provides it automatically)user=awaitUser.create(name="John", email="john@example.com")
users=awaitUser.find({"context.name": "John"}) # Use context. prefix for fieldsuser=awaitUser.get(user_id) # Returns None if not foundifuser:
awaituser.save()
awaituser.delete()
# Efficient countingtotal_users=awaitUser.count() # Count all usersactive_users=awaitUser.count({"context.active": True}) # Count filtered users using query dictactive_users=awaitUser.count(active=True) # Count filtered users using keyword argumentsSet SERVERLESS_MODE=true to force serverless-safe behavior (strict synchronous request lifecycle, no fire-and-forget background task assumptions). When unset, jvspatial auto-detects AWS Lambda via runtime environment variables. Use is_serverless_mode() from jvspatial.runtime.serverless to check mode at runtime.
For deferred work across invocations, use dispatch_deferred_task() from jvspatial.serverless. On AWS, Lambda async invoke and optional EventBridge deliver JSON to your app; with the Lambda Web Adapter, Server applies best-effort AWS_LWA_PASS_THROUGH_PATH / AWS_LWA_INVOKE_MODE defaults when LWA is detected (see docs/md/serverless-mode.md); set them in IaC when the extension must read them before Python starts. Register task handlers with register_deferred_invoke_handler() in jvspatial.serverless.deferred_invoke.
Merge order when constructing Server is: ServerConfig defaults → allowlisted JVSPATIAL_* environment → config= dict or keyword arguments (later wins). Import ServerConfig from jvspatial.api when you need the schema outside Server.
fromjvspatial.apiimportServer# Basic serverserver=Server(
title="My API",
description="API description",
version="1.0.0",
db_type="json",
db_path="./jvdb"
)
# Server with authentication# Auth settings live under the nested `auth` group; flat top-level# auth kwargs are ignored by ServerConfig.server=Server(
title="Secure API",
auth=dict(
auth_enabled=True, # Registers /auth/register, /auth/login, /auth/logoutjwt_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 registereddb_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
- REST API Guide - API design patterns
- Server API Guide - Server configuration
- Authentication Guide - Authentication patterns
- Entity Reference - Node, Edge, Walker classes
- Serverless mode - Deferred tasks, Lambda Web Adapter, and LWA env defaults
- Production Deployment - Production checklist and security
- 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
- Observability - Structured DB logging, slow-query threshold, MetricsRecorder, OpenTelemetry adapter
- Performance Benchmarks - Regression-detection bench suite (pytest-benchmark + CI workflow)
- API Stability - Public/internal/experimental tiers and deprecation policy
- Contributing - Dev loop, conventions, label glossary
- Releasing - Maintainer-only release procedure
- Security Policy - Vulnerability disclosure
- Code of Conduct - Contributor Covenant 2.1
jvspatial — a foundational object-spatial application development framework — was created by Eldon Marks (@eldonm), who serves as its lead maintainer.
See AUTHORS for the full list of authors and contributors. Copyright and licensing terms are set out in the LICENSE.
We welcome contributions! Please see our Contributing Guide for details.
This project is licensed under the MIT License - see the LICENSE file for details.