doc-changes-5-7 #4

Merged
anonpenguin merged 8 commits from doc-changes-5-7 into main 2025-07-09 13:01:30 +00:00
31 changed files with 7111 additions and 2100 deletions

View File

@ -0,0 +1,391 @@
# DebrosFramework Development Guidelines
## Code Style and Standards
### TypeScript Configuration
- **Strict Mode**: Always use strict TypeScript configuration
- **Decorators**: Enable `experimentalDecorators` and `emitDecoratorMetadata`
- **Target**: ES2020 for modern JavaScript features
- **Module System**: ES modules with CommonJS interop
### Code Formatting
- **Prettier**: Use Prettier for consistent code formatting
- **ESLint**: Follow ESLint rules for code quality
- **Indentation**: 2 spaces for all files
- **Line Length**: Max 120 characters per line
- **Semicolons**: Always use semicolons
- **Quotes**: Single quotes for strings, double quotes for JSX
### Naming Conventions
- **Classes**: PascalCase (e.g., `UserModel`, `QueryBuilder`)
- **Functions/Methods**: camelCase (e.g., `createUser`, `findById`)
- **Variables**: camelCase (e.g., `userId`, `queryResult`)
- **Constants**: UPPER_SNAKE_CASE (e.g., `DEFAULT_CACHE_SIZE`)
- **Files**: PascalCase for classes, camelCase for utilities
- **Interfaces**: PascalCase with descriptive names (e.g., `ModelConfig`)
## Framework Architecture Patterns
### Model System
```typescript
// Always extend BaseModel for data models
@Model({
scope: 'user' | 'global',
type: 'docstore',
sharding: { strategy: 'hash', count: 4, key: 'fieldName' }
})
export class ModelName extends BaseModel {
@Field({ type: 'string', required: true })
propertyName: string;
@BelongsTo(() => RelatedModel, 'foreignKey')
relation: RelatedModel;
}
```
### Query Patterns
```typescript
// Use chainable query builder pattern
const results = await Model.query()
.where('field', 'operator', value)
.with(['relationship1', 'relationship2'])
.orderBy('field', 'direction')
.limit(count)
.find();
// Prefer specific methods over generic ones
const user = await User.findById(id); // Good
const user = await User.query().where('id', id).findOne(); // Less preferred
```
### Error Handling
```typescript
// Always use try-catch for async operations
try {
const result = await someAsyncOperation();
return result;
} catch (error) {
console.error('Operation failed:', error);
throw new DebrosFrameworkError('Descriptive error message', { originalError: error });
}
// Validate inputs early
if (!userId || typeof userId !== 'string') {
throw new ValidationError('User ID must be a non-empty string');
}
```
### Service Layer Pattern
```typescript
// Encapsulate business logic in service classes
export class UserService {
async createUser(userData: CreateUserData): Promise<User> {
// Validation
await this.validateUserData(userData);
// Business logic
const user = await User.create(userData);
// Post-processing
await this.sendWelcomeEmail(user);
return user;
}
private async validateUserData(data: CreateUserData): Promise<void> {
// Validation logic
}
}
```
## Testing Standards
### Unit Tests
- **Jest**: Use Jest for all unit testing
- **Mocking**: Mock external dependencies (OrbitDB, IPFS)
- **Coverage**: Aim for >90% code coverage
- **Structure**: One test file per source file
- **Naming**: `*.test.ts` for test files
```typescript
describe('ModelName', () => {
let model: ModelName;
beforeEach(() => {
model = new ModelName();
});
describe('methodName', () => {
it('should handle normal case', async () => {
// Arrange
const input = 'test value';
// Act
const result = await model.methodName(input);
// Assert
expect(result).toBeDefined();
expect(result.property).toBe('expected value');
});
it('should throw error for invalid input', async () => {
// Arrange & Act & Assert
await expect(model.methodName(null)).rejects.toThrow('Expected error message');
});
});
});
```
### Integration Tests
- **Docker**: Use Docker for real integration tests
- **Scenarios**: Test complete user workflows
- **Data**: Use realistic test data
- **Cleanup**: Always clean up test data
## Performance Guidelines
### Query Optimization
```typescript
// Use selective field loading when possible
const users = await User.query().select(['id', 'username']).find();
// Prefer eager loading for predictable relationships
const posts = await Post.query().with(['author', 'comments']).find();
// Use caching for expensive queries
const popularPosts = await Post.query()
.where('likeCount', '>', 100)
.cache(300) // Cache for 5 minutes
.find();
```
### Memory Management
- **Lazy Loading**: Use lazy loading for large datasets
- **Pagination**: Always use pagination for large result sets
- **Cache Limits**: Set appropriate cache size limits
- **Cleanup**: Clean up resources in finally blocks
### Database Design
- **Sharding**: Design effective sharding strategies
- **Indexing**: Use indexes for frequently queried fields
- **Relationships**: Avoid deep relationship chains
- **Data Types**: Use appropriate data types for storage efficiency
## Security Considerations
### Input Validation
```typescript
// Always validate and sanitize inputs
@Field({
type: 'string',
required: true,
validate: (value: string) => value.length >= 3 && value.length <= 50,
transform: (value: string) => value.trim().toLowerCase()
})
username: string;
```
### Access Control
- **User Scoping**: Use user-scoped models for private data
- **Validation**: Validate user permissions before operations
- **Sanitization**: Sanitize all user inputs
- **Encryption**: Use encryption for sensitive data
### Error Messages
- **Security**: Don't expose internal system details in error messages
- **Logging**: Log security-relevant events
- **Validation**: Provide clear validation error messages
## Documentation Standards
### Code Documentation
```typescript
/**
* Creates a new user with the provided data.
*
* @param userData - The user data to create
* @param options - Additional creation options
* @returns Promise resolving to the created user
* @throws ValidationError if user data is invalid
* @throws DuplicateError if username or email already exists
*
* @example
* ```typescript
* const user = await userService.createUser({
* username: 'alice',
* email: 'alice@example.com'
* });
* ```
*/
async createUser(userData: CreateUserData, options?: CreateOptions): Promise<User> {
// Implementation
}
```
### README Updates
- Keep README.md up to date with latest features
- Include practical examples
- Document breaking changes
- Provide migration guides
### API Documentation
- Document all public APIs
- Include parameter types and return types
- Provide usage examples
- Document error conditions
## Common Patterns and Anti-Patterns
### ✅ Good Patterns
#### Model Definition
```typescript
@Model({
scope: 'user',
type: 'docstore',
sharding: { strategy: 'hash', count: 4, key: 'userId' }
})
export class Post extends BaseModel {
@Field({ type: 'string', required: true, maxLength: 200 })
title: string;
@Field({ type: 'string', required: true })
content: string;
@BeforeCreate()
setDefaults() {
this.createdAt = Date.now();
this.updatedAt = Date.now();
}
}
```
#### Service Methods
```typescript
async createPost(authorId: string, postData: CreatePostData): Promise<Post> {
// Validate input
if (!authorId) throw new ValidationError('Author ID is required');
// Check permissions
const author = await User.findById(authorId);
if (!author) throw new NotFoundError('Author not found');
// Create post
const post = await Post.create({
...postData,
authorId,
});
// Post-processing
await this.notifyFollowers(author, post);
return post;
}
```
### ❌ Anti-Patterns
#### Avoid Direct Database Access
```typescript
// Bad: Direct database manipulation
const db = await orbitdb.open('posts');
await db.put('key', data);
// Good: Use model methods
const post = await Post.create(data);
```
#### Avoid Synchronous Operations
```typescript
// Bad: Synchronous file operations
const data = fs.readFileSync('file.json');
// Good: Async operations
const data = await fs.promises.readFile('file.json');
```
#### Avoid Deep Relationship Chains
```typescript
// Bad: Deep relationship loading
const posts = await Post.query()
.with(['author.profile.settings.preferences'])
.find();
// Good: Load only what you need
const posts = await Post.query()
.with(['author'])
.find();
```
## Migration Guidelines
### Schema Changes
```typescript
// Create migration for schema changes
const migration = createMigration('add_user_avatar', '1.1.0')
.addField('User', 'avatarUrl', {
type: 'string',
required: false
})
.transformData('User', (user) => ({
...user,
avatarUrl: user.avatarUrl || null
}))
.build();
```
### Backwards Compatibility
- Always maintain backwards compatibility in minor versions
- Deprecate features before removing them
- Provide migration paths for breaking changes
- Document all changes in CHANGELOG.md
## Deployment Considerations
### Environment Configuration
- Use environment variables for configuration
- Provide default configurations for development
- Validate configuration on startup
- Document required environment variables
### Production Readiness
- Enable production optimizations
- Configure appropriate cache sizes
- Set up monitoring and logging
- Implement health checks
### Performance Monitoring
- Monitor query performance
- Track cache hit rates
- Monitor memory usage
- Set up alerts for errors
## Contributing Guidelines
### Pull Request Process
1. Fork the repository
2. Create feature branch from main
3. Implement changes with tests
4. Update documentation
5. Submit pull request with description
### Code Review Checklist
- [ ] Code follows style guidelines
- [ ] Tests are included and passing
- [ ] Documentation is updated
- [ ] No breaking changes (or properly documented)
- [ ] Performance implications considered
- [ ] Security implications reviewed
### Commit Message Format
```
type(scope): description
body (optional)
footer (optional)
```
Types: feat, fix, docs, style, refactor, test, chore
These guidelines ensure consistent, maintainable, and high-quality code throughout the DebrosFramework project.

249
.claude/project-overview.md Normal file
View File

@ -0,0 +1,249 @@
# DebrosFramework Project Overview
## Project Identity
**DebrosFramework** is a powerful Node.js framework that provides an ORM-like abstraction over OrbitDB and IPFS, making it easy to build scalable decentralized applications.
- **Package Name**: `@debros/network`
- **Version**: 0.5.1-beta (Active Development)
- **License**: GNU GPL v3.0
- **Language**: TypeScript
- **Framework Type**: Decentralized Application Framework
## What This Project Does
DebrosFramework simplifies the development of decentralized applications by providing:
### Core Capabilities
- **Model-based Abstraction**: Define data models using decorators and TypeScript classes
- **Automatic Database Management**: Handle user-scoped and global databases automatically
- **Smart Sharding**: Distribute data across multiple databases for scalability
- **Advanced Query System**: Rich query capabilities with relationship loading and caching
- **Automatic Features**: Built-in pinning strategies and PubSub event publishing
- **Migration System**: Schema evolution and data transformation capabilities
- **Type Safety**: Full TypeScript support with strong typing throughout
### Key Features
1. **🏗️ Model-Driven Development**: Familiar decorator patterns for data models
2. **🔍 Powerful Query System**: Complex queries with relationship loading
3. **🚀 Automatic Scaling**: Handle millions of users with automatic sharding
4. **🔄 Schema Evolution**: Safe data structure migrations
5. **🔗 Rich Relationships**: Complex relationships between models
6. **⚡ Performance Features**: Query caching, eager loading, optimized pagination
7. **🎯 Model Hooks**: Lifecycle hooks for business logic
## Architecture Overview
The framework is built around several core components:
1. **Models & Decorators**: Define data structure and behavior
2. **Database Manager**: Handles database creation and management
3. **Shard Manager**: Distributes data across multiple databases
4. **Query System**: Processes queries with optimization and caching
5. **Relationship Manager**: Handles complex relationships between models
6. **Migration System**: Manages schema evolution over time
7. **Automatic Features**: Pinning, PubSub, and performance optimization
## Technology Stack
### Core Dependencies
- **OrbitDB**: Distributed peer-to-peer database on IPFS
- **IPFS/Helia**: Distributed file system for data storage
- **libp2p**: Peer-to-peer networking stack
- **TypeScript**: Strong typing and modern JavaScript features
### Key Libraries
- `@orbitdb/core`: Core OrbitDB functionality
- `@helia/unixfs`: IPFS file system operations
- `@libp2p/*`: Various libp2p modules for networking
- `winston`: Logging
- `node-cache`: In-memory caching
- `express`: HTTP server for integration tests
## Project Structure
```
src/framework/
├── core/ # Core framework components
│ ├── ConfigManager.ts
│ ├── DatabaseManager.ts
│ └── ModelRegistry.ts
├── models/ # Model system and decorators
│ ├── BaseModel.ts
│ └── decorators/
├── query/ # Query builder and execution
│ ├── QueryBuilder.ts
│ ├── QueryExecutor.ts
│ ├── QueryOptimizer.ts
│ └── QueryCache.ts
├── relationships/ # Relationship management
│ ├── RelationshipManager.ts
│ ├── LazyLoader.ts
│ └── RelationshipCache.ts
├── sharding/ # Data sharding logic
│ └── ShardManager.ts
├── migrations/ # Schema migration system
│ ├── MigrationManager.ts
│ └── MigrationBuilder.ts
├── pinning/ # Automatic pinning features
│ └── PinningManager.ts
├── pubsub/ # Event publishing system
│ └── PubSubManager.ts
├── services/ # External service integrations
│ ├── OrbitDBService.ts
│ ├── IPFSService.ts
│ └── RealOrbitDBService.ts
└── types/ # TypeScript type definitions
├── framework.ts
├── models.ts
└── queries.ts
```
## Development Status
**Current State**: Beta (v0.5.1-beta) - Active Development
### What's Stable
- ✅ Core model system with decorators
- ✅ Basic CRUD operations
- ✅ Query builder and execution
- ✅ Relationship management
- ✅ Database management and sharding
- ✅ Migration system foundation
### What's In Development
- 🚧 Advanced query optimization
- 🚧 Performance optimization features
- 🚧 Production-ready configurations
- 🚧 Extended relationship types
- 🚧 Enhanced error handling
### Testing
- **Unit Tests**: Comprehensive test suite using Jest
- **Integration Tests**: Docker-based real-world scenarios
- **Blog Scenario**: Complete blogging platform test case
## Key Concepts
### Model Scoping
- **Global Models**: Shared across all users (e.g., User profiles)
- **User Models**: Each user has their own database instance (e.g., Posts, Comments)
### Sharding Strategies
- **Hash Sharding**: Distribute data based on key hashing
- **Range Sharding**: Distribute data based on value ranges
- **User Sharding**: Dedicated shards per user or user group
### Query System
- **Chainable API**: Fluent interface for building queries
- **Type Safety**: Full TypeScript support with auto-completion
- **Relationship Loading**: Eager and lazy loading strategies
- **Caching**: Intelligent query result caching
### Relationships
- **BelongsTo**: Many-to-one relationships
- **HasMany**: One-to-many relationships
- **HasOne**: One-to-one relationships
- **ManyToMany**: Many-to-many relationships (with through tables)
## Common Use Cases
### 1. Social Platforms
- User profiles and authentication
- Posts, comments, and reactions
- Friend networks and messaging
- Activity feeds and notifications
### 2. Content Management
- Blogs and publishing platforms
- Document management systems
- Media galleries and collections
- Version control for content
### 3. Collaborative Applications
- Real-time document editing
- Project management tools
- Team collaboration platforms
- Knowledge bases and wikis
### 4. Marketplace Applications
- Product catalogs and inventory
- User reviews and ratings
- Order management systems
- Payment and transaction records
## Development Workflow
### Prerequisites
- Node.js 18.0 or higher
- TypeScript knowledge
- Basic understanding of IPFS and OrbitDB concepts
- Docker (for integration tests)
### Build Process
```bash
npm run build # Compile TypeScript
npm run dev # Development with watch mode
npm run lint # ESLint code checking
npm run format # Prettier code formatting
```
### Testing
```bash
npm run test:unit # Fast unit tests with mocks
npm run test:real # Full integration tests with Docker
npm run test:blog-integration # Blog scenario integration tests
```
### Key Development Principles
1. **Type Safety First**: Everything is strongly typed
2. **Decorator-Based**: Use decorators for configuration
3. **Async/Await**: All operations are promise-based
4. **Error Handling**: Comprehensive error management
5. **Performance**: Built-in optimization and caching
6. **Scalability**: Designed for distributed systems
## API Patterns
### Model Definition
```typescript
@Model({
scope: 'user',
type: 'docstore',
sharding: { strategy: 'hash', count: 4, key: 'userId' }
})
class Post extends BaseModel {
@Field({ type: 'string', required: true })
title: string;
@BelongsTo(() => User, 'userId')
user: User;
}
```
### Query Operations
```typescript
const posts = await Post.query()
.where('isPublished', true)
.where('createdAt', '>', Date.now() - 7 * 24 * 60 * 60 * 1000)
.with(['user', 'comments'])
.orderBy('likeCount', 'desc')
.limit(20)
.find();
```
### Lifecycle Hooks
```typescript
class User extends BaseModel {
@BeforeCreate()
setupNewUser() {
this.registeredAt = Date.now();
}
@AfterCreate()
async sendWelcomeEmail() {
// Business logic after creation
}
}
```
This framework makes building decentralized applications feel like traditional web development while providing the benefits of distributed, peer-to-peer systems.

View File

@ -0,0 +1,607 @@
# DebrosFramework Technical Reference
## Core Architecture Components
### DebrosFramework Main Class
**Location**: `src/framework/DebrosFramework.ts`
The main framework class that orchestrates all components:
```typescript
export class DebrosFramework {
// Core services
private orbitDBService: FrameworkOrbitDBService;
private ipfsService: FrameworkIPFSService;
// Framework components
private databaseManager: DatabaseManager;
private shardManager: ShardManager;
private queryCache: QueryCache;
private relationshipManager: RelationshipManager;
private pinningManager: PinningManager;
private pubsubManager: PubSubManager;
private migrationManager: MigrationManager;
// Lifecycle methods
async initialize(orbitDBService?, ipfsService?, config?): Promise<void>
async start(): Promise<void>
async stop(): Promise<void>
getStatus(): FrameworkStatus
getMetrics(): FrameworkMetrics
}
```
### BaseModel Class
**Location**: `src/framework/models/BaseModel.ts`
Abstract base class for all data models:
```typescript
export abstract class BaseModel {
// Instance properties
public id: string;
public _loadedRelations: Map<string, any>;
protected _isDirty: boolean;
protected _isNew: boolean;
// Static configuration
static modelName: string;
static storeType: StoreType;
static scope: 'user' | 'global';
static sharding?: ShardingConfig;
static fields: Map<string, FieldConfig>;
static relationships: Map<string, RelationshipConfig>;
// CRUD operations
async save(): Promise<this>
static async create<T>(data: any): Promise<T>
static async findById<T>(id: string): Promise<T | null>
static query<T>(): QueryBuilder<T>
async delete(): Promise<void>
// Lifecycle hooks
async beforeCreate(): Promise<void>
async afterCreate(): Promise<void>
async beforeUpdate(): Promise<void>
async afterUpdate(): Promise<void>
async beforeDelete(): Promise<void>
async afterDelete(): Promise<void>
}
```
## Decorator System
### @Model Decorator
**Location**: `src/framework/models/decorators/Model.ts`
Configures model behavior and database storage:
```typescript
interface ModelConfig {
scope: 'user' | 'global'; // Database scope
type: StoreType; // OrbitDB store type
sharding?: ShardingConfig; // Data distribution strategy
pinning?: PinningConfig; // Automatic pinning configuration
pubsub?: PubSubConfig; // Event publishing configuration
validation?: ValidationConfig; // Model-level validation
}
@Model({
scope: 'user',
type: 'docstore',
sharding: { strategy: 'hash', count: 4, key: 'userId' }
})
```
### @Field Decorator
**Location**: `src/framework/models/decorators/Field.ts`
Defines field properties and validation:
```typescript
interface FieldConfig {
type: FieldType; // Data type
required?: boolean; // Required field
unique?: boolean; // Unique constraint
default?: any | (() => any); // Default value
validate?: (value: any) => boolean; // Custom validation
transform?: (value: any) => any; // Data transformation
serialize?: boolean; // Include in serialization
index?: boolean; // Create index for field
virtual?: boolean; // Virtual field (not stored)
}
@Field({
type: 'string',
required: true,
unique: true,
validate: (value: string) => value.length >= 3,
transform: (value: string) => value.trim().toLowerCase()
})
```
### Relationship Decorators
**Location**: `src/framework/models/decorators/relationships.ts`
```typescript
// Many-to-one relationship
@BelongsTo(() => User, 'userId')
author: User;
// One-to-many relationship
@HasMany(() => Post, 'authorId')
posts: Post[];
// One-to-one relationship
@HasOne(() => Profile, 'userId')
profile: Profile;
// Many-to-many relationship
@ManyToMany(() => Tag, 'post_tags', 'tag_id', 'post_id')
tags: Tag[];
```
### Lifecycle Hook Decorators
**Location**: `src/framework/models/decorators/hooks.ts`
```typescript
@BeforeCreate()
setupDefaults() {
this.createdAt = Date.now();
}
@AfterCreate()
async sendNotification() {
await this.notifyUsers();
}
@BeforeUpdate()
updateTimestamp() {
this.updatedAt = Date.now();
}
@AfterUpdate()
async invalidateCache() {
await this.clearRelatedCache();
}
@BeforeDelete()
async checkPermissions() {
if (!this.canDelete()) {
throw new Error('Cannot delete this record');
}
}
@AfterDelete()
async cleanupRelations() {
await this.removeRelatedData();
}
```
## Query System
### QueryBuilder Class
**Location**: `src/framework/query/QueryBuilder.ts`
Fluent interface for building queries:
```typescript
export class QueryBuilder<T> {
// Filter methods
where(field: string, value: any): QueryBuilder<T>
where(field: string, operator: string, value: any): QueryBuilder<T>
where(callback: (query: QueryBuilder<T>) => void): QueryBuilder<T>
orWhere(field: string, value: any): QueryBuilder<T>
whereIn(field: string, values: any[]): QueryBuilder<T>
whereNotIn(field: string, values: any[]): QueryBuilder<T>
whereNull(field: string): QueryBuilder<T>
whereNotNull(field: string): QueryBuilder<T>
whereLike(field: string, pattern: string): QueryBuilder<T>
// Relationship methods
with(relations: string[]): QueryBuilder<T>
withCount(relations: string[]): QueryBuilder<T>
// Ordering and limiting
orderBy(field: string, direction?: 'asc' | 'desc'): QueryBuilder<T>
limit(count: number): QueryBuilder<T>
offset(count: number): QueryBuilder<T>
// Field selection
select(fields: string[]): QueryBuilder<T>
distinct(field?: string): QueryBuilder<T>
// Caching
cache(ttl?: number): QueryBuilder<T>
// Execution methods
find(): Promise<T[]>
findOne(): Promise<T | null>
first(): Promise<T | null>
count(): Promise<number>
exists(): Promise<boolean>
paginate(page: number, perPage: number): Promise<PaginationResult<T>>
// Aggregation
sum(field: string): Promise<number>
avg(field: string): Promise<number>
min(field: string): Promise<any>
max(field: string): Promise<any>
}
```
### Query Operators
```typescript
type QueryOperator =
| 'eq' // Equal to
| 'ne' // Not equal to
| 'gt' // Greater than
| 'gte' // Greater than or equal
| 'lt' // Less than
| 'lte' // Less than or equal
| 'in' // In array
| 'not in' // Not in array
| 'like' // Pattern matching
| 'regex' // Regular expression
| 'is null' // Is null
| 'is not null' // Is not null
| 'includes' // Array includes value
| 'includes any'// Array includes any of values
| 'includes all'// Array includes all values
```
## Database Management
### DatabaseManager Class
**Location**: `src/framework/core/DatabaseManager.ts`
Handles database creation and lifecycle:
```typescript
export class DatabaseManager {
// Database operations
async getGlobalDatabase(modelName: string): Promise<Database>
async getUserDatabase(userId: string, modelName: string): Promise<Database>
async createDatabase(name: string, type: StoreType, options?: any): Promise<Database>
async closeDatabase(name: string): Promise<void>
// Document operations
async getDocument(database: Database, storeType: StoreType, id: string): Promise<any>
async putDocument(database: Database, storeType: StoreType, id: string, data: any): Promise<void>
async deleteDocument(database: Database, storeType: StoreType, id: string): Promise<void>
async queryDocuments(database: Database, storeType: StoreType, query: any): Promise<any[]>
// Lifecycle
async initialize(orbitDBService: FrameworkOrbitDBService): Promise<void>
async stop(): Promise<void>
}
```
### ShardManager Class
**Location**: `src/framework/sharding/ShardManager.ts`
Handles data distribution across shards:
```typescript
export class ShardManager {
// Shard operations
getShardForKey(modelName: string, key: string): Shard
getShardForRange(modelName: string, value: any): Shard
getAllShards(modelName: string): Shard[]
// Shard management
async createShards(modelName: string, config: ShardingConfig): Promise<void>
async redistributeData(modelName: string, newShardCount: number): Promise<void>
// Configuration
setShardingConfig(modelName: string, config: ShardingConfig): void
getShardingConfig(modelName: string): ShardingConfig | undefined
}
interface ShardingConfig {
strategy: 'hash' | 'range' | 'user';
count: number;
key: string;
ranges?: ShardRange[];
}
interface Shard {
id: string;
database: Database;
range?: { min: any; max: any };
}
```
## Relationship Management
### RelationshipManager Class
**Location**: `src/framework/relationships/RelationshipManager.ts`
Handles loading and caching of model relationships:
```typescript
export class RelationshipManager {
// Relationship loading
async loadRelationship(model: BaseModel, relationshipName: string): Promise<any>
async loadRelationships(model: BaseModel, relationshipNames: string[]): Promise<void>
async eagerLoadRelationships(models: BaseModel[], relationshipNames: string[]): Promise<void>
// Relationship operations
async attachRelationship(model: BaseModel, relationshipName: string, relatedModel: BaseModel): Promise<void>
async detachRelationship(model: BaseModel, relationshipName: string, relatedModel: BaseModel): Promise<void>
async syncRelationship(model: BaseModel, relationshipName: string, relatedModels: BaseModel[]): Promise<void>
// Caching
getCachedRelationship(model: BaseModel, relationshipName: string): any
setCachedRelationship(model: BaseModel, relationshipName: string, data: any): void
clearRelationshipCache(model: BaseModel, relationshipName?: string): void
}
```
## Migration System
### MigrationManager Class
**Location**: `src/framework/migrations/MigrationManager.ts`
Handles schema evolution and data transformation:
```typescript
export class MigrationManager {
// Migration operations
async runMigration(migrationId: string): Promise<MigrationResult>
async rollbackMigration(migrationId: string): Promise<MigrationResult>
async runPendingMigrations(): Promise<MigrationResult[]>
// Migration management
registerMigration(migration: Migration): void
getPendingMigrations(): Migration[]
getAppliedMigrations(): Promise<string[]>
// Status
getMigrationStatus(): Promise<MigrationStatus>
}
interface Migration {
id: string;
version: string;
name: string;
description: string;
targetModels: string[];
up: MigrationOperation[];
down: MigrationOperation[];
dependencies?: string[];
validators?: MigrationValidator[];
}
```
### MigrationBuilder Class
**Location**: `src/framework/migrations/MigrationBuilder.ts`
Fluent interface for creating migrations:
```typescript
export function createMigration(name: string, version: string): MigrationBuilder {
return new MigrationBuilder(name, version);
}
export class MigrationBuilder {
// Field operations
addField(modelName: string, fieldName: string, config: FieldConfig): MigrationBuilder
removeField(modelName: string, fieldName: string): MigrationBuilder
modifyField(modelName: string, fieldName: string, config: FieldConfig): MigrationBuilder
renameField(modelName: string, oldName: string, newName: string): MigrationBuilder
// Index operations
addIndex(modelName: string, fields: string[], options?: IndexOptions): MigrationBuilder
removeIndex(modelName: string, indexName: string): MigrationBuilder
// Data transformation
transformData(modelName: string, transformer: (data: any) => any): MigrationBuilder
// Validation
addValidator(name: string, validator: MigrationValidator): MigrationBuilder
// Build migration
build(): Migration
}
```
## Caching System
### QueryCache Class
**Location**: `src/framework/query/QueryCache.ts`
Intelligent caching of query results:
```typescript
export class QueryCache {
// Cache operations
get(key: string): Promise<any>
set(key: string, value: any, ttl?: number): Promise<void>
delete(key: string): Promise<void>
clear(): Promise<void>
// Cache management
invalidateModelCache(modelName: string): Promise<void>
invalidateUserCache(userId: string): Promise<void>
// Statistics
getStats(): CacheStats
getHitRate(): number
}
```
### RelationshipCache Class
**Location**: `src/framework/relationships/RelationshipCache.ts`
Specialized caching for relationship data:
```typescript
export class RelationshipCache {
// Relationship caching
getCachedRelationship(modelId: string, relationshipName: string): any
setCachedRelationship(modelId: string, relationshipName: string, data: any, ttl?: number): void
invalidateRelationship(modelId: string, relationshipName: string): void
// Batch operations
preloadRelationships(modelIds: string[], relationshipNames: string[]): Promise<void>
warmCache(modelName: string, relationshipName: string): Promise<void>
}
```
## Type Definitions
### Framework Types
**Location**: `src/framework/types/framework.ts`
```typescript
export interface FrameworkConfig {
cache?: CacheConfig;
queryOptimization?: QueryOptimizationConfig;
automaticPinning?: PinningConfig;
pubsub?: PubSubConfig;
development?: DevelopmentConfig;
}
export interface CacheConfig {
enabled?: boolean;
maxSize?: number;
ttl?: number;
}
export type StoreType = 'docstore' | 'eventlog' | 'keyvalue' | 'counter' | 'feed';
```
### Model Types
**Location**: `src/framework/types/models.ts`
```typescript
export interface FieldConfig {
type: FieldType;
required?: boolean;
unique?: boolean;
default?: any | (() => any);
validate?: (value: any) => boolean;
transform?: (value: any) => any;
serialize?: boolean;
index?: boolean;
virtual?: boolean;
}
export type FieldType = 'string' | 'number' | 'boolean' | 'array' | 'object' | 'date';
export interface RelationshipConfig {
type: 'belongsTo' | 'hasMany' | 'hasOne' | 'manyToMany';
target: () => typeof BaseModel;
foreignKey: string;
localKey?: string;
through?: string;
throughForeignKey?: string;
throughLocalKey?: string;
}
```
### Query Types
**Location**: `src/framework/types/queries.ts`
```typescript
export interface QueryOptions {
where?: WhereClause[];
orderBy?: OrderByClause[];
limit?: number;
offset?: number;
with?: string[];
cache?: boolean | number;
}
export interface WhereClause {
field: string;
operator: QueryOperator;
value: any;
boolean: 'and' | 'or';
}
export interface OrderByClause {
field: string;
direction: 'asc' | 'desc';
}
export interface PaginationResult<T> {
data: T[];
total: number;
page: number;
perPage: number;
totalPages: number;
hasNext: boolean;
hasPrev: boolean;
}
```
## Error Handling
### Framework Errors
```typescript
export class DebrosFrameworkError extends Error {
code: string;
details?: any;
constructor(message: string, code?: string, details?: any) {
super(message);
this.name = 'DebrosFrameworkError';
this.code = code || 'UNKNOWN_ERROR';
this.details = details;
}
}
export class ValidationError extends DebrosFrameworkError {
field: string;
value: any;
constraint: string;
}
export class QueryError extends DebrosFrameworkError {
query: string;
parameters?: any[];
}
export class RelationshipError extends DebrosFrameworkError {
modelName: string;
relationshipName: string;
relatedModel: string;
}
```
## Performance Optimization
### Query Optimization
**Location**: `src/framework/query/QueryOptimizer.ts`
```typescript
export class QueryOptimizer {
// Query optimization
optimizeQuery(query: QueryBuilder<any>): QueryBuilder<any>
analyzeQueryPerformance(query: QueryBuilder<any>): Promise<QueryAnalysis>
suggestIndexes(modelName: string): Promise<IndexSuggestion[]>
// Statistics
getSlowQueries(): Promise<SlowQuery[]>
getQueryStats(): Promise<QueryStats>
}
```
### LazyLoader Class
**Location**: `src/framework/relationships/LazyLoader.ts`
```typescript
export class LazyLoader {
// Lazy loading
async loadOnDemand(model: BaseModel, relationshipName: string): Promise<any>
async batchLoad(models: BaseModel[], relationshipName: string): Promise<void>
// Configuration
setBatchSize(size: number): void
setLoadingStrategy(strategy: 'immediate' | 'batched' | 'deferred'): void
}
```
This technical reference provides the implementation details needed to work effectively with the DebrosFramework codebase.

View File

@ -2,8 +2,14 @@
"src/**/*.{js,ts}": [
"prettier --write",
"eslint --fix",
"pnpm run test:unit",
"npm run build"
],
"tests/**/*.{js,ts}": [
"prettier --write",
"eslint --fix",
"pnpm run test:unit"
],
"*.{json,md}": [
"prettier --write"
]

347
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,347 @@
# Contributing to DebrosFramework
Thank you for your interest in contributing to DebrosFramework! This document provides guidelines and information for contributors.
## Development Status
DebrosFramework is currently in **beta (v0.5.0-beta)** and under active development. We welcome contributions from the community to help improve the framework.
## Getting Started
### Prerequisites
- Node.js 18.0 or higher
- npm or pnpm package manager
- Git
- TypeScript knowledge
- Familiarity with IPFS and OrbitDB concepts
### Development Setup
1. **Fork and Clone**
```bash
git clone https://github.com/YOUR_USERNAME/network.git
cd network
```
2. **Install Dependencies**
```bash
pnpm install
```
3. **Build the Project**
```bash
pnpm run build
```
4. **Run Tests**
```bash
# Unit tests
pnpm run test:unit
# Integration tests
pnpm run test:real
```
## Project Structure
```
src/framework/
├── core/ # Core framework components
├── models/ # Model system and decorators
├── query/ # Query builder and execution
├── relationships/ # Relationship management
├── sharding/ # Data sharding logic
├── migrations/ # Schema migration system
├── pinning/ # Automatic pinning features
├── pubsub/ # Event publishing system
└── types/ # TypeScript type definitions
docs/docs/ # Documentation source
tests/ # Test suites
└── real-integration/ # Integration test scenarios
```
## How to Contribute
### Types of Contributions
We welcome the following types of contributions:
1. **🐛 Bug Reports** - Report issues and bugs
2. **✨ Feature Requests** - Suggest new features
3. **📖 Documentation** - Improve docs and examples
4. **🔧 Code Contributions** - Bug fixes and new features
5. **🧪 Testing** - Add tests and improve test coverage
6. **💡 Examples** - Create usage examples and tutorials
### Bug Reports
When reporting bugs, please include:
- **Clear description** of the issue
- **Steps to reproduce** the problem
- **Expected vs actual behavior**
- **Environment details** (Node.js version, OS, etc.)
- **Code examples** that demonstrate the issue
- **Error messages** and stack traces
Use our bug report template:
````markdown
## Bug Description
[Clear description of the bug]
## Steps to Reproduce
1. [First step]
2. [Second step]
3. [etc.]
## Expected Behavior
[What you expected to happen]
## Actual Behavior
[What actually happened]
## Environment
- DebrosFramework version: [version]
- Node.js version: [version]
- OS: [operating system]
## Code Example
```typescript
// Minimal code example that reproduces the issue
```
````
````
### Feature Requests
For feature requests, please provide:
- **Clear use case** and motivation
- **Detailed description** of the proposed feature
- **API design suggestions** (if applicable)
- **Examples** of how it would be used
- **Alternatives considered**
### Code Contributions
#### Before You Start
1. **Check existing issues** to avoid duplicate work
2. **Discuss large changes** in an issue first
3. **Follow the coding standards** outlined below
4. **Write tests** for your changes
5. **Update documentation** as needed
#### Development Workflow
1. **Create a feature branch**
```bash
git checkout -b feature/your-feature-name
````
2. **Make your changes**
- Write clean, well-documented code
- Follow TypeScript best practices
- Add tests for new functionality
- Update relevant documentation
3. **Test your changes**
```bash
pnpm run test:unit
pnpm run test:real
pnpm run lint
```
4. **Commit your changes**
```bash
git add .
git commit -m "feat: add new feature description"
```
5. **Push and create PR**
```bash
git push origin feature/your-feature-name
```
#### Commit Message Format
We use conventional commits for consistent commit messages:
```
type(scope): description
body (optional)
footer (optional)
```
**Types:**
- `feat`: New features
- `fix`: Bug fixes
- `docs`: Documentation changes
- `style`: Code style changes (formatting, etc.)
- `refactor`: Code refactoring
- `test`: Adding or updating tests
- `chore`: Maintenance tasks
**Examples:**
```
feat(models): add support for computed fields
fix(query): resolve relationship loading issue
docs(readme): update installation instructions
```
#### Code Style Guidelines
1. **TypeScript**
- Use strict TypeScript configuration
- Provide proper type annotations
- Use interfaces for object types
- Follow naming conventions
2. **Formatting**
- Use Prettier for code formatting
- Run `pnpm run format` before committing
- Use 2 spaces for indentation
3. **ESLint**
- Follow ESLint rules
- Run `pnpm run lint` and fix any issues
- Use `pnpm run lint:fix` for auto-fixes
4. **Documentation**
- Add JSDoc comments for public APIs
- Update relevant documentation files
- Include code examples where appropriate
#### Testing Guidelines
1. **Unit Tests**
- Write tests for all new functionality
- Use Jest for unit testing
- Aim for high code coverage
- Test edge cases and error conditions
2. **Integration Tests**
- Add integration tests for significant features
- Test real-world scenarios
- Use the blog scenario tests as reference
3. **Test Structure**
```typescript
describe('FeatureName', () => {
beforeEach(() => {
// Setup
});
it('should behave correctly in normal case', () => {
// Test implementation
});
it('should handle edge case', () => {
// Edge case test
});
it('should throw error for invalid input', () => {
// Error case test
});
});
```
## Documentation
### Documentation Structure
- **README.md** - Overview and quick start
- **docs/docs/intro.md** - Framework introduction
- **docs/docs/getting-started.md** - Setup guide
- **docs/docs/core-concepts/** - Architecture and concepts
- **docs/docs/api/** - API reference
- **docs/docs/examples/** - Usage examples
### Writing Documentation
1. **Use clear, concise language**
2. **Provide code examples**
3. **Include both basic and advanced usage**
4. **Keep examples up-to-date**
5. **Add diagrams where helpful**
### Building Documentation
```bash
cd docs
npm install
npm run start # Development server
npm run build # Production build
```
## Release Process
Releases are managed by the core team and follow semantic versioning:
- **Patch** (0.5.1): Bug fixes and small improvements
- **Minor** (0.6.0): New features, backward compatible
- **Major** (1.0.0): Breaking changes
## Community Guidelines
### Code of Conduct
We are committed to providing a welcoming and inclusive environment. Please:
- **Be respectful** and considerate
- **Use inclusive language**
- **Accept constructive feedback**
- **Focus on what's best** for the community
- **Show empathy** towards other contributors
### Getting Help
- **GitHub Issues** - For bug reports and feature requests
- **GitHub Discussions** - For questions and community discussion
- **Discord** - For real-time chat and support
## Recognition
Contributors will be recognized in:
- **CONTRIBUTORS.md** file
- **Release notes** for significant contributions
- **Documentation credits** for doc contributions
## Questions?
If you have questions about contributing, please:
1. Check existing documentation
2. Search GitHub issues
3. Ask in GitHub Discussions
4. Contact the maintainers
Thank you for contributing to DebrosFramework! 🚀

601
README.md
View File

@ -1,21 +1,18 @@
# @debros/network
Core networking functionality for the Debros decentralized network. This package provides a powerful database interface with advanced features built on IPFS and OrbitDB for decentralized applications.
**DebrosFramework** - A powerful Node.js framework that provides an ORM-like abstraction over OrbitDB and IPFS, making it easy to build scalable decentralized applications.
## Features
## What is DebrosFramework?
- Rich database-like API with TypeScript support
- Multiple database store types (KeyValue, Document, Feed, Counter)
- Document operations with schema validation
- Advanced querying with pagination, sorting and filtering
- Transaction support for batch operations
- Built-in file storage with metadata
- Real-time subscriptions for data changes
- Memory caching for performance
- Connection pooling for managing multiple database instances
- Index creation for faster queries
- Comprehensive error handling with error codes
- Performance metrics and monitoring
DebrosFramework simplifies the development of decentralized applications by providing:
- **Model-based Abstraction**: Define your data models using decorators and TypeScript classes
- **Automatic Database Management**: Handle user-scoped and global databases automatically
- **Smart Sharding**: Distribute data across multiple databases for scalability
- **Advanced Query System**: Rich query capabilities with relationship loading and caching
- **Automatic Features**: Built-in pinning strategies and PubSub event publishing
- **Migration System**: Schema evolution and data transformation capabilities
- **Type Safety**: Full TypeScript support with strong typing throughout
## Installation
@ -23,280 +20,366 @@ Core networking functionality for the Debros decentralized network. This package
npm install @debros/network
```
## Basic Usage
## Quick Start
### 1. Define Your Models
```typescript
import { initDB, create, get, query, uploadFile, logger } from '@debros/network';
import { BaseModel, Model, Field, HasMany } from '@debros/network';
@Model({
scope: 'global',
type: 'docstore',
sharding: { strategy: 'hash', count: 4, key: 'id' },
})
export class User extends BaseModel {
@Field({ type: 'string', required: true, unique: true })
username: string;
@Field({ type: 'string', required: true, unique: true })
email: string;
@HasMany(() => Post, 'userId')
posts: Post[];
}
@Model({
scope: 'user',
type: 'docstore',
sharding: { strategy: 'user', count: 2, key: 'userId' },
})
export class Post extends BaseModel {
@Field({ type: 'string', required: true })
title: string;
@Field({ type: 'string', required: true })
content: string;
@Field({ type: 'string', required: true })
userId: string;
}
```
### 2. Initialize the Framework
```typescript
import { DebrosFramework } from '@debros/network';
import { setupOrbitDB, setupIPFS } from './services';
// Initialize the database service
async function startApp() {
try {
// Initialize with default configuration
await initDB();
logger.info('Database initialized successfully');
// Initialize services
const orbitDBService = await setupOrbitDB();
const ipfsService = await setupIPFS();
// Create a new user document
const userId = 'user123';
const user = {
username: 'johndoe',
walletAddress: '0x1234567890',
avatar: null,
};
// Initialize framework
const framework = new DebrosFramework({
features: {
queryCache: true,
automaticPinning: true,
pubsub: true,
},
});
const result = await create('users', userId, user);
logger.info(`Created user with ID: ${result.id}`);
await framework.initialize(orbitDBService, ipfsService);
console.log('✅ DebrosFramework initialized successfully!');
// Get a user by ID
const retrievedUser = await get('users', userId);
logger.info('User:', retrievedUser);
// Create a user
const user = await User.create({
username: 'alice',
email: 'alice@example.com',
});
// Query users with filtering
const activeUsers = await query('users', (user) => user.isActive === true, {
limit: 10,
sort: { field: 'createdAt', order: 'desc' },
});
logger.info(`Found ${activeUsers.total} active users`);
// Create a post
const post = await Post.create({
title: 'My First Post',
content: 'Hello DebrosFramework!',
userId: user.id,
});
// Upload a file
const fileData = Buffer.from('File content');
const fileUpload = await uploadFile(fileData, { filename: 'document.txt' });
logger.info(`Uploaded file with CID: ${fileUpload.cid}`);
// Query with relationships
const usersWithPosts = await User.query().with(['posts']).where('username', 'alice').find();
return true;
} catch (error) {
logger.error('Failed to start app:', error);
throw error;
console.log('User:', usersWithPosts[0]);
console.log('Posts:', usersWithPosts[0].posts);
}
```
## Key Features
### 🏗️ Model-Driven Development
Define your data models using familiar decorator patterns:
```typescript
@Model({
scope: 'user',
type: 'docstore',
sharding: { strategy: 'hash', count: 4, key: 'userId' },
})
class Post extends BaseModel {
@Field({ type: 'string', required: true })
title: string;
@BelongsTo(() => User, 'userId')
user: User;
}
```
### 🔍 Powerful Query System
Build complex queries with relationship loading:
```typescript
const users = await User.query()
.where('isActive', true)
.where('registeredAt', '>', Date.now() - 30 * 24 * 60 * 60 * 1000)
.with(['posts', 'followers'])
.orderBy('username')
.limit(20)
.find();
```
### 🚀 Automatic Scaling
Handle millions of users with automatic sharding and pinning:
```typescript
// Framework automatically:
// - Creates user-scoped databases
// - Distributes data across shards
// - Manages pinning strategies
// - Optimizes query routing
```
### 🔄 Schema Evolution
Migrate your data structures safely:
```typescript
const migration = createMigration('add_user_profiles', '1.1.0')
.addField('User', 'profilePicture', { type: 'string', required: false })
.addField('User', 'bio', { type: 'string', required: false })
.transformData('User', (user) => ({
...user,
displayName: user.username || 'Anonymous',
}))
.build();
```
### 🔗 Rich Relationships
Handle complex relationships between models:
```typescript
@Model({ scope: 'global' })
class User extends BaseModel {
@HasMany(() => Post, 'userId')
posts: Post[];
@ManyToMany(() => User, 'followers', 'following')
followers: User[];
}
// Load user with all relationships
const user = await User.findById(userId, {
with: ['posts.comments', 'followers.posts'],
});
```
### ⚡ Performance Features
```typescript
// Query caching
const cachedUsers = await User.query()
.where('isActive', true)
.cache(300) // Cache for 5 minutes
.find();
// Eager loading
const usersWithPosts = await User.query().with(['posts.comments']).find();
// Optimized pagination
const page = await User.query().orderBy('createdAt', 'desc').paginate(1, 20);
```
### 🎯 Model Hooks
```typescript
export class User extends BaseModel {
@BeforeCreate()
async beforeCreate() {
this.createdAt = Date.now();
// Hash password, validate data, etc.
}
@AfterCreate()
async afterCreate() {
// Send welcome email, create defaults, etc.
}
}
startApp();
```
## Database Store Types
The library supports multiple OrbitDB store types, each optimized for different use cases:
```typescript
import { create, get, update, StoreType } from '@debros/network';
// Default KeyValue store (for general use)
await create('users', 'user1', { name: 'Alice' });
// Document store (better for complex documents with indexing)
await create(
'posts',
'post1',
{ title: 'Hello', content: '...' },
{ storeType: StoreType.DOCSTORE },
);
// Feed/EventLog store (append-only, good for immutable logs)
await create('events', 'evt1', { type: 'login', user: 'alice' }, { storeType: StoreType.FEED });
// Counter store (for numeric counters)
await create('stats', 'visits', { value: 0 }, { storeType: StoreType.COUNTER });
// Increment a counter
await update('stats', 'visits', { increment: 1 }, { storeType: StoreType.COUNTER });
// Get counter value
const stats = await get('stats', 'visits', { storeType: StoreType.COUNTER });
console.log(`Visit count: ${stats.value}`);
```
## Advanced Features
### Schema Validation
```typescript
import { defineSchema, create } from '@debros/network';
// Define a schema
defineSchema('users', {
properties: {
username: {
type: 'string',
required: true,
min: 3,
max: 20,
},
email: {
type: 'string',
pattern: '^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$',
},
age: {
type: 'number',
min: 18,
},
},
required: ['username'],
});
// Document creation will be validated against the schema
await create('users', 'user1', {
username: 'alice',
email: 'alice@example.com',
age: 25,
});
```
### Transactions
```typescript
import { createTransaction, commitTransaction } from '@debros/network';
// Create a transaction
const transaction = createTransaction();
// Add multiple operations
transaction
.create('posts', 'post1', { title: 'Hello World', content: '...' })
.update('users', 'user1', { postCount: 1 })
.delete('drafts', 'draft1');
// Commit all operations
const result = await commitTransaction(transaction);
console.log(`Transaction completed with ${result.results.length} operations`);
```
### Event Subscriptions
```typescript
import { subscribe } from '@debros/network';
// Subscribe to document changes
const unsubscribe = subscribe('document:created', (data) => {
console.log(`New document created in ${data.collection}:`, data.id);
console.log('Document data:', data.document);
});
// Other event types
// subscribe('document:updated', (data) => { ... });
// subscribe('document:deleted', (data) => { ... });
// Later, unsubscribe when done
unsubscribe();
```
### Pagination and Sorting
```typescript
import { list, query } from '@debros/network';
// List with pagination and sorting
const page1 = await list('users', {
limit: 10,
offset: 0,
sort: { field: 'createdAt', order: 'desc' },
});
// Query with pagination
const results = await query('users', (user) => user.age > 21, { limit: 10, offset: 20 });
console.log(`Found ${results.total} matches, showing ${results.documents.length}`);
console.log(`Has more pages: ${results.hasMore}`);
```
### TypeScript Support
```typescript
import { get, update, query } from '@debros/network';
interface User {
username: string;
email: string;
age: number;
createdAt: number;
updatedAt: number;
}
// Type-safe operations
const user = await get<User>('users', 'user1');
await update<User>('users', 'user1', { age: 26 });
const results = await query<User>('users', (user) => user.age > 21);
```
### Connection Management
```typescript
import { initDB, closeConnection } from '@debros/network';
// Create multiple connections
const conn1 = await initDB('connection1');
const conn2 = await initDB('connection2');
// Use specific connection
await create('users', 'user1', { name: 'Alice' }, { connectionId: conn1 });
// Close a specific connection
await closeConnection(conn1);
```
## API Reference
### Core Database Operations
### Framework Management
- `initDB(connectionId?: string): Promise<string>` - Initialize the database
- `create<T>(collection, id, data, options?): Promise<CreateResult>` - Create a document
- `get<T>(collection, id, options?): Promise<T | null>` - Get a document by ID
- `update<T>(collection, id, data, options?): Promise<UpdateResult>` - Update a document
- `remove(collection, id, options?): Promise<boolean>` - Delete a document
- `list<T>(collection, options?): Promise<PaginatedResult<T>>` - List documents with pagination
- `query<T>(collection, filter, options?): Promise<PaginatedResult<T>>` - Query documents
- `stopDB(): Promise<void>` - Stop the database service
- `new DebrosFramework(config?)` - Create framework instance
- `framework.initialize(orbitDBService, ipfsService, config?)` - Initialize framework
- `framework.start()` - Start the framework
- `framework.stop()` - Stop the framework
- `framework.getStatus()` - Get framework status
### Store Types
### Model Operations
- `StoreType.KEYVALUE` - Key-value pair storage (default)
- `StoreType.DOCSTORE` - Document storage with indexing
- `StoreType.FEED` - Append-only log
- `StoreType.EVENTLOG` - Alias for FEED
- `StoreType.COUNTER` - Numeric counter
- `Model.create(data)` - Create a new model instance
- `Model.findById(id, options?)` - Find model by ID
- `Model.findOne(criteria, options?)` - Find single model
- `Model.query()` - Start a query builder
- `model.save()` - Save model changes
- `model.delete()` - Delete model instance
### Schema Validation
### Query System
- `defineSchema(collection, schema): void` - Define a schema for a collection
- `Model.query().where(field, operator, value)` - Add where condition
- `Model.query().with(relationships)` - Eager load relationships
- `Model.query().orderBy(field, direction)` - Add ordering
- `Model.query().limit(count)` - Limit results
- `Model.query().offset(count)` - Add offset
- `Model.query().paginate(page, perPage)` - Paginate results
- `Model.query().cache(ttl)` - Cache query results
- `Model.query().find()` - Execute query
- `Model.query().count()` - Count results
### Transactions
### Decorators
- `createTransaction(connectionId?): Transaction` - Create a new transaction
- `commitTransaction(transaction): Promise<{success, results}>` - Execute the transaction
- `Transaction.create<T>(collection, id, data): Transaction` - Add a create operation
- `Transaction.update<T>(collection, id, data): Transaction` - Add an update operation
- `Transaction.delete(collection, id): Transaction` - Add a delete operation
- `@Model(config)` - Define model configuration
- `@Field(config)` - Define field properties
- `@BelongsTo(target, foreignKey)` - Many-to-one relationship
- `@HasMany(target, foreignKey)` - One-to-many relationship
- `@HasOne(target, foreignKey)` - One-to-one relationship
- `@ManyToMany(target, through)` - Many-to-many relationship
- `@BeforeCreate()`, `@AfterCreate()` - Lifecycle hooks
- `@BeforeUpdate()`, `@AfterUpdate()` - Update hooks
- `@BeforeDelete()`, `@AfterDelete()` - Delete hooks
### Event Subscriptions
### Migration System
- `subscribe(event, callback): () => void` - Subscribe to database events, returns unsubscribe function
- Event types: 'document:created', 'document:updated', 'document:deleted'
### File Operations
- `uploadFile(fileData, options?): Promise<FileUploadResult>` - Upload a file
- `getFile(cid, options?): Promise<FileResult>` - Get a file by CID
- `deleteFile(cid, options?): Promise<boolean>` - Delete a file
### Connection Management
- `closeConnection(connectionId): Promise<boolean>` - Close a specific connection
### Indexes and Performance
- `createIndex(collection, field, options?): Promise<boolean>` - Create an index
- `createMigration(name, version)` - Create new migration
- `migration.addField(model, field, config)` - Add field to model
- `migration.removeField(model, field)` - Remove field from model
- `migration.transformData(model, transformer)` - Transform existing data
- `migrationManager.runPendingMigrations()` - Run pending migrations
## Configuration
### Framework Configuration
```typescript
import { config, initDB } from '@debros/network';
import { DebrosFramework, PRODUCTION_CONFIG, DEVELOPMENT_CONFIG } from '@debros/network';
// Configure (optional)
config.env.fingerprint = 'my-unique-app-id';
config.env.port = 9000;
config.ipfs.blockstorePath = './custom-path/blockstore';
config.orbitdb.directory = './custom-path/orbitdb';
// Development configuration
const framework = new DebrosFramework({
...DEVELOPMENT_CONFIG,
features: {
queryCache: true,
automaticPinning: false,
pubsub: true,
relationshipCache: true,
autoMigration: true,
},
performance: {
queryTimeout: 30000,
batchSize: 50,
},
monitoring: {
enableMetrics: true,
logLevel: 'debug',
},
});
// Initialize with configuration
await initDB();
// Production configuration
const prodFramework = new DebrosFramework({
...PRODUCTION_CONFIG,
performance: {
queryTimeout: 10000,
batchSize: 200,
maxConcurrentOperations: 500,
},
});
```
### Model Configuration
```typescript
@Model({
scope: 'global', // 'user' or 'global'
type: 'docstore', // OrbitDB store type
sharding: {
strategy: 'hash', // 'hash', 'range', or 'user'
count: 4, // Number of shards
key: 'id', // Sharding key
},
pinning: {
strategy: 'popularity', // Pinning strategy
factor: 2,
},
})
export class MyModel extends BaseModel {
// Model definition
}
```
## Architecture Overview
DebrosFramework is built around several core components:
1. **Models & Decorators**: Define your data structure and behavior
2. **Database Manager**: Handles database creation and management
3. **Shard Manager**: Distributes data across multiple databases
4. **Query System**: Processes queries with optimization and caching
5. **Relationship Manager**: Handles complex relationships between models
6. **Migration System**: Manages schema evolution over time
7. **Automatic Features**: Pinning, PubSub, and performance optimization
### Key Benefits
- **Scalability**: Automatic sharding and distributed data management
- **Performance**: Built-in caching, query optimization, and lazy loading
- **Developer Experience**: Familiar ORM patterns with TypeScript support
- **Flexibility**: Support for various data patterns and relationships
- **Reliability**: Comprehensive error handling and recovery mechanisms
## Getting Started
Ready to build your first decentralized application? Check out our comprehensive documentation:
- **[📖 Complete Documentation](./docs)** - Comprehensive guides and examples
- **[🚀 Getting Started Guide](./docs/docs/getting-started.md)** - Set up your development environment
- **[🏗️ Architecture Overview](./docs/docs/core-concepts/architecture.md)** - Understand how the framework works
- **[📝 API Reference](./docs/docs/api/overview.md)** - Complete API documentation
- **[💡 Examples](./docs/docs/examples/basic-usage.md)** - Practical usage examples
## Testing
```bash
# Run unit tests
npm run test:unit
# Run integration tests
npm run test:real
# Run specific blog scenario integration test
npm run test:blog-integration
```
## Contributing
We welcome contributions! Please see our [Contributing Guide](./CONTRIBUTING.md) for details.
## License
This project is licensed under the GNU GPL v3.0 License - see the [LICENSE](./LICENSE) file for details.
---
**DebrosFramework** - Making decentralized application development as simple as traditional web development, while providing the benefits of distributed systems.

810
docs/docs/api/base-model.md Normal file
View File

@ -0,0 +1,810 @@
---
sidebar_position: 3
---
# BaseModel Class
The `BaseModel` class is the abstract base class for all data models in Debros Network. It provides ORM-like functionality with automatic database management, validation, relationships, and lifecycle hooks.
## Class Definition
```typescript
abstract class BaseModel {
// Instance properties
id: string;
createdAt?: number;
updatedAt?: number;
// Static methods
static async create<T extends BaseModel>(
this: ModelConstructor<T>,
data: Partial<T>,
options?: CreateOptions,
): Promise<T>;
static async findById<T extends BaseModel>(
this: ModelConstructor<T>,
id: string,
options?: FindOptions,
): Promise<T | null>;
static async findOne<T extends BaseModel>(
this: ModelConstructor<T>,
criteria: Partial<T>,
options?: FindOptions,
): Promise<T | null>;
static query<T extends BaseModel>(this: ModelConstructor<T>): QueryBuilder<T>;
// Instance methods
save(options?: SaveOptions): Promise<this>;
delete(options?: DeleteOptions): Promise<boolean>;
reload(options?: ReloadOptions): Promise<this>;
validate(): Promise<ValidationResult>;
toJSON(): Record<string, any>;
clone(): this;
}
```
## Static Methods
### create(data, options?)
Creates a new model instance and saves it to the database.
**Parameters:**
- `data`: Partial model data
- `options` (optional): Creation options
**Returns:** `Promise<T>` - The created model instance
**Throws:**
- `ValidationError` - If validation fails
- `DatabaseError` - If database operation fails
**Example:**
```typescript
import { BaseModel, Model, Field } from '@debros/network';
@Model({
scope: 'global',
type: 'docstore',
})
class User extends BaseModel {
@Field({ type: 'string', required: true, unique: true })
username: string;
@Field({ type: 'string', required: true, unique: true })
email: string;
@Field({ type: 'number', required: false, default: 0 })
score: number;
}
// Create a new user
const user = await User.create({
username: 'alice',
email: 'alice@example.com',
score: 100,
});
console.log(user.id); // Generated ID
console.log(user.username); // 'alice'
console.log(user.createdAt); // Timestamp
```
**With validation:**
```typescript
try {
const user = await User.create({
username: 'ab', // Too short
email: 'invalid-email', // Invalid format
});
} catch (error) {
if (error instanceof ValidationError) {
console.log('Validation failed:', error.field, error.constraint);
}
}
```
**With options:**
```typescript
const user = await User.create(
{
username: 'bob',
email: 'bob@example.com',
},
{
validate: true,
skipHooks: false,
userId: 'user123', // For user-scoped models
},
);
```
### findById(id, options?)
Finds a model instance by its ID.
**Parameters:**
- `id`: The model ID to search for
- `options` (optional): Find options
**Returns:** `Promise<T | null>` - The found model or null
**Example:**
```typescript
// Basic find
const user = await User.findById('user123');
if (user) {
console.log('Found user:', user.username);
} else {
console.log('User not found');
}
// With relationships
const user = await User.findById('user123', {
with: ['posts', 'profile'],
});
// With specific user context
const user = await User.findById('user123', {
userId: 'current-user-id',
});
```
### findOne(criteria, options?)
Finds the first model instance matching the criteria.
**Parameters:**
- `criteria`: Partial model data to match
- `options` (optional): Find options
**Returns:** `Promise<T | null>` - The found model or null
**Example:**
```typescript
// Find by field
const user = await User.findOne({
username: 'alice',
});
// Find with multiple criteria
const user = await User.findOne({
email: 'alice@example.com',
isActive: true,
});
// With options
const user = await User.findOne(
{
username: 'alice',
},
{
with: ['posts'],
cache: 300, // Cache for 5 minutes
},
);
```
### query()
Returns a query builder for complex queries.
**Returns:** `QueryBuilder<T>` - Query builder instance
**Example:**
```typescript
// Basic query
const users = await User.query()
.where('isActive', true)
.orderBy('createdAt', 'desc')
.limit(10)
.find();
// Complex query with relationships
const activeUsers = await User.query()
.where('isActive', true)
.where('score', '>', 100)
.where('registeredAt', '>', Date.now() - 30 * 24 * 60 * 60 * 1000)
.with(['posts.comments', 'profile'])
.orderBy('score', 'desc')
.paginate(1, 20);
// Query with caching
const cachedUsers = await User.query()
.where('isActive', true)
.cache(600) // Cache for 10 minutes
.find();
```
## Instance Methods
### save(options?)
Saves the current model instance to the database.
**Parameters:**
- `options` (optional): Save options
**Returns:** `Promise<this>` - The saved model instance
**Example:**
```typescript
const user = await User.findById('user123');
user.email = 'newemail@example.com';
user.score += 10;
await user.save();
console.log('User updated');
// With options
await user.save({
validate: true,
skipHooks: false,
});
```
### delete(options?)
Deletes the model instance from the database.
**Parameters:**
- `options` (optional): Delete options
**Returns:** `Promise<boolean>` - True if deletion was successful
**Example:**
```typescript
const user = await User.findById('user123');
if (user) {
const deleted = await user.delete();
console.log('User deleted:', deleted);
}
// With options
await user.delete({
skipHooks: false,
cascade: true, // Delete related records
});
```
### reload(options?)
Reloads the model instance from the database.
**Parameters:**
- `options` (optional): Reload options
**Returns:** `Promise<this>` - The reloaded model instance
**Example:**
```typescript
const user = await User.findById('user123');
// Model might be updated elsewhere
await user.reload();
// With relationships
await user.reload({
with: ['posts', 'profile'],
});
```
### validate()
Validates the current model instance.
**Returns:** `Promise<ValidationResult>` - Validation result
**Example:**
```typescript
const user = new User();
user.username = 'alice';
user.email = 'invalid-email';
const result = await user.validate();
if (!result.valid) {
console.log('Validation errors:', result.errors);
// [{ field: 'email', constraint: 'must be valid email', value: 'invalid-email' }]
}
```
### toJSON()
Converts the model instance to a plain JavaScript object.
**Returns:** `Record<string, any>` - Plain object representation
**Example:**
```typescript
const user = await User.findById('user123');
const userObj = user.toJSON();
console.log(userObj);
// {
// id: 'user123',
// username: 'alice',
// email: 'alice@example.com',
// score: 100,
// createdAt: 1234567890,
// updatedAt: 1234567890
// }
// Useful for JSON serialization
const jsonString = JSON.stringify(user); // Calls toJSON() automatically
```
### clone()
Creates a deep copy of the model instance (without ID).
**Returns:** `this` - Cloned model instance
**Example:**
```typescript
const user = await User.findById('user123');
const userCopy = user.clone();
userCopy.username = 'alice_copy';
await userCopy.save(); // Creates new record
console.log(user.id !== userCopy.id); // true
```
## Lifecycle Hooks
### Hook Decorators
Models can define lifecycle hooks using decorators:
```typescript
@Model({ scope: 'global', type: 'docstore' })
class User extends BaseModel {
@Field({ type: 'string', required: true })
username: string;
@Field({ type: 'string', required: true })
email: string;
@Field({ type: 'number', required: false })
loginCount: number = 0;
@BeforeCreate()
async beforeCreateHook() {
this.createdAt = Date.now();
this.updatedAt = Date.now();
// Validate unique username
const existing = await User.findOne({ username: this.username });
if (existing) {
throw new ValidationError('username', this.username, 'must be unique');
}
}
@AfterCreate()
async afterCreateHook() {
console.log(`New user created: ${this.username}`);
// Send welcome email
await this.sendWelcomeEmail();
// Create default settings
await this.createDefaultSettings();
}
@BeforeUpdate()
async beforeUpdateHook() {
this.updatedAt = Date.now();
}
@AfterUpdate()
async afterUpdateHook() {
console.log(`User updated: ${this.username}`);
}
@BeforeDelete()
async beforeDeleteHook() {
// Clean up related data
await this.deleteRelatedPosts();
}
@AfterDelete()
async afterDeleteHook() {
console.log(`User deleted: ${this.username}`);
}
// Custom methods
private async sendWelcomeEmail() {
// Implementation
}
private async createDefaultSettings() {
// Implementation
}
private async deleteRelatedPosts() {
// Implementation
}
}
```
### Available Hook Types
| Hook | Trigger | Usage |
| ----------------- | ------------------------------- | --------------------------------------- |
| `@BeforeCreate()` | Before creating new record | Validation, default values, preparation |
| `@AfterCreate()` | After creating new record | Notifications, related record creation |
| `@BeforeUpdate()` | Before updating existing record | Validation, timestamp updates, logging |
| `@AfterUpdate()` | After updating existing record | Cache invalidation, notifications |
| `@BeforeDelete()` | Before deleting record | Cleanup, validation, logging |
| `@AfterDelete()` | After deleting record | Cleanup, notifications, cascade deletes |
| `@BeforeSave()` | Before save (create or update) | Common validation, timestamps |
| `@AfterSave()` | After save (create or update) | Common post-processing |
## Validation
### Field Validation
```typescript
@Model({ scope: 'global', type: 'docstore' })
class User extends BaseModel {
@Field({
type: 'string',
required: true,
unique: true,
minLength: 3,
maxLength: 20,
validate: (username: string) => /^[a-zA-Z0-9_]+$/.test(username),
transform: (username: string) => username.toLowerCase(),
})
username: string;
@Field({
type: 'string',
required: true,
unique: true,
validate: (email: string) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email),
transform: (email: string) => email.toLowerCase(),
})
email: string;
@Field({
type: 'number',
required: false,
default: 0,
validate: (score: number) => score >= 0 && score <= 1000,
})
score: number;
@Field({
type: 'array',
required: false,
default: [],
validate: (tags: string[]) => tags.length <= 10,
})
tags: string[];
}
```
### Custom Validation Methods
```typescript
@Model({ scope: 'global', type: 'docstore' })
class User extends BaseModel {
@Field({ type: 'string', required: true })
username: string;
@Field({ type: 'string', required: true })
email: string;
@Field({ type: 'string', required: true })
password: string;
// Custom validation method
async customValidation(): Promise<ValidationResult> {
const errors: ValidationError[] = [];
// Check username availability
if (this.username) {
const existing = await User.findOne({ username: this.username });
if (existing && existing.id !== this.id) {
errors.push(new ValidationError('username', this.username, 'already taken'));
}
}
// Check email format and availability
if (this.email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(this.email)) {
errors.push(new ValidationError('email', this.email, 'invalid format'));
}
const existing = await User.findOne({ email: this.email });
if (existing && existing.id !== this.id) {
errors.push(new ValidationError('email', this.email, 'already registered'));
}
}
// Check password strength
if (this.password && this.password.length < 8) {
errors.push(new ValidationError('password', this.password, 'must be at least 8 characters'));
}
return {
valid: errors.length === 0,
errors,
};
}
@BeforeCreate()
@BeforeUpdate()
async validateBeforeSave() {
const result = await this.customValidation();
if (!result.valid) {
throw new ValidationError('model', this, 'custom validation failed', result.errors);
}
}
}
```
## Configuration Interfaces
### ModelConstructor Type
```typescript
type ModelConstructor<T extends BaseModel> = new () => T;
```
### Options Interfaces
```typescript
interface CreateOptions {
validate?: boolean;
skipHooks?: boolean;
userId?: string; // For user-scoped models
}
interface FindOptions {
with?: string[]; // Relationship names to eager load
cache?: boolean | number; // Cache result
userId?: string; // For user-scoped models
}
interface SaveOptions {
validate?: boolean;
skipHooks?: boolean;
upsert?: boolean;
}
interface DeleteOptions {
skipHooks?: boolean;
cascade?: boolean; // Delete related records
}
interface ReloadOptions {
with?: string[]; // Relationship names to eager load
}
```
### Validation Types
```typescript
interface ValidationResult {
valid: boolean;
errors: ValidationError[];
}
class ValidationError extends Error {
constructor(
public field: string,
public value: any,
public constraint: string,
public details?: any,
) {
super(`Validation failed for field '${field}': ${constraint}`);
}
}
```
## Error Handling
### Common Errors
```typescript
// Validation errors
try {
const user = await User.create({
username: 'a', // Too short
email: 'invalid',
});
} catch (error) {
if (error instanceof ValidationError) {
console.log(`Field ${error.field} failed: ${error.constraint}`);
}
}
// Not found errors
const user = await User.findById('non-existent-id');
if (!user) {
throw new NotFoundError('User', 'non-existent-id');
}
// Database errors
try {
await user.save();
} catch (error) {
if (error instanceof DatabaseError) {
console.log('Database operation failed:', error.message);
}
}
```
## Complete Example
### Blog Post Model
```typescript
import {
BaseModel,
Model,
Field,
BelongsTo,
HasMany,
BeforeCreate,
AfterCreate,
} from '@debros/network';
import { User } from './User';
import { Comment } from './Comment';
@Model({
scope: 'user',
type: 'docstore',
sharding: {
strategy: 'user',
count: 2,
key: 'authorId',
},
})
export class Post extends BaseModel {
@Field({
type: 'string',
required: true,
minLength: 1,
maxLength: 200,
})
title: string;
@Field({
type: 'string',
required: true,
minLength: 1,
maxLength: 10000,
})
content: string;
@Field({ type: 'string', required: true })
authorId: string;
@Field({
type: 'array',
required: false,
default: [],
transform: (tags: string[]) => tags.map((tag) => tag.toLowerCase()),
})
tags: string[];
@Field({ type: 'boolean', required: false, default: false })
isPublished: boolean;
@Field({ type: 'number', required: false, default: 0 })
viewCount: number;
@Field({ type: 'number', required: false })
publishedAt?: number;
// Relationships
@BelongsTo(() => User, 'authorId')
author: User;
@HasMany(() => Comment, 'postId')
comments: Comment[];
@BeforeCreate()
setupNewPost() {
this.createdAt = Date.now();
this.updatedAt = Date.now();
this.viewCount = 0;
}
@AfterCreate()
async afterPostCreated() {
console.log(`New post created: ${this.title}`);
// Update author's post count
const author = await User.findById(this.authorId);
if (author) {
author.postCount = (author.postCount || 0) + 1;
await author.save();
}
}
// Custom methods
async publish(): Promise<void> {
this.isPublished = true;
this.publishedAt = Date.now();
await this.save();
}
async incrementViews(): Promise<void> {
this.viewCount += 1;
await this.save({ skipHooks: true }); // Skip hooks for performance
}
async getCommentCount(): Promise<number> {
return await Comment.query().where('postId', this.id).count();
}
async getTopComments(limit: number = 5): Promise<Comment[]> {
return await Comment.query()
.where('postId', this.id)
.orderBy('likeCount', 'desc')
.limit(limit)
.with(['author'])
.find();
}
}
// Usage examples
async function blogExamples() {
// Create a post
const post = await Post.create({
title: 'My First Post',
content: 'This is the content of my first post...',
authorId: 'user123',
tags: ['JavaScript', 'Web Development'],
});
// Find posts by author
const userPosts = await Post.query()
.where('authorId', 'user123')
.where('isPublished', true)
.orderBy('publishedAt', 'desc')
.with(['author', 'comments.author'])
.find();
// Publish a post
await post.publish();
// Get post with comments
const postWithComments = await Post.findById(post.id, {
with: ['author', 'comments.author'],
});
console.log('Post:', postWithComments?.title);
console.log('Author:', postWithComments?.author.username);
console.log('Comments:', postWithComments?.comments.length);
}
```
This comprehensive BaseModel documentation covers all the essential functionality for working with models in Debros Network, including CRUD operations, validation, relationships, hooks, and real-world usage examples.

View File

@ -0,0 +1,828 @@
---
sidebar_position: 4
---
# QueryBuilder Class
The `QueryBuilder` class provides a fluent API for constructing complex database queries. It supports filtering, sorting, relationships, pagination, and caching with type safety throughout.
## Class Definition
```typescript
class QueryBuilder<T extends BaseModel> {
// Filtering methods
where(field: string, value: any): QueryBuilder<T>;
where(field: string, operator: QueryOperator, value: any): QueryBuilder<T>;
whereIn(field: string, values: any[]): QueryBuilder<T>;
whereNotIn(field: string, values: any[]): QueryBuilder<T>;
whereNull(field: string): QueryBuilder<T>;
whereNotNull(field: string): QueryBuilder<T>;
whereBetween(field: string, min: any, max: any): QueryBuilder<T>;
whereRaw(condition: string, parameters?: any[]): QueryBuilder<T>;
// Logical operators
and(): QueryBuilder<T>;
or(): QueryBuilder<T>;
not(): QueryBuilder<T>;
// Sorting
orderBy(field: string, direction?: 'asc' | 'desc'): QueryBuilder<T>;
orderByRaw(orderClause: string): QueryBuilder<T>;
// Limiting and pagination
limit(count: number): QueryBuilder<T>;
offset(count: number): QueryBuilder<T>;
paginate(page: number, perPage: number): Promise<PaginatedResult<T>>;
// Relationships
with(relationships: string[]): QueryBuilder<T>;
withCount(relationships: string[]): QueryBuilder<T>;
whereHas(relationship: string, callback?: (query: QueryBuilder<any>) => void): QueryBuilder<T>;
whereDoesntHave(relationship: string): QueryBuilder<T>;
// Aggregation
count(): Promise<number>;
sum(field: string): Promise<number>;
avg(field: string): Promise<number>;
min(field: string): Promise<any>;
max(field: string): Promise<any>;
// Caching
cache(ttl?: number): QueryBuilder<T>;
fresh(): QueryBuilder<T>;
// Execution
find(): Promise<T[]>;
findOne(): Promise<T | null>;
first(): Promise<T | null>;
get(): Promise<T[]>;
// Advanced features
distinct(field?: string): QueryBuilder<T>;
groupBy(field: string): QueryBuilder<T>;
having(field: string, operator: QueryOperator, value: any): QueryBuilder<T>;
// Query info
toSQL(): string;
getParameters(): any[];
explain(): Promise<QueryPlan>;
}
```
## Filtering Methods
### where(field, value) / where(field, operator, value)
Adds a WHERE condition to the query.
**Parameters:**
- `field`: Field name to filter on
- `value`: Value to compare (when using equals operator)
- `operator`: Comparison operator
- `value`: Value to compare against
**Returns:** `QueryBuilder<T>` - Builder instance for chaining
**Example:**
```typescript
// Basic equality
const activeUsers = await User.query().where('isActive', true).find();
// With operators
const highScoreUsers = await User.query()
.where('score', '>', 1000)
.where('registeredAt', '>=', Date.now() - 30 * 24 * 60 * 60 * 1000)
.find();
// String operations
const usersWithAlice = await User.query().where('username', 'like', '%alice%').find();
// Array operations
const adminUsers = await User.query().where('roles', 'includes', 'admin').find();
```
### whereIn(field, values)
Filters records where field value is in the provided array.
**Parameters:**
- `field`: Field name
- `values`: Array of values to match
**Returns:** `QueryBuilder<T>`
**Example:**
```typescript
// Find users with specific IDs
const users = await User.query().whereIn('id', ['user1', 'user2', 'user3']).find();
// Find posts with specific tags
const posts = await Post.query().whereIn('category', ['tech', 'programming', 'tutorial']).find();
```
### whereNotIn(field, values)
Filters records where field value is NOT in the provided array.
**Parameters:**
- `field`: Field name
- `values`: Array of values to exclude
**Returns:** `QueryBuilder<T>`
**Example:**
```typescript
// Exclude specific users
const users = await User.query().whereNotIn('status', ['banned', 'suspended']).find();
```
### whereNull(field) / whereNotNull(field)
Filters records based on null values.
**Parameters:**
- `field`: Field name to check
**Returns:** `QueryBuilder<T>`
**Example:**
```typescript
// Find users without profile pictures
const usersWithoutAvatars = await User.query().whereNull('avatarUrl').find();
// Find users with profile pictures
const usersWithAvatars = await User.query().whereNotNull('avatarUrl').find();
```
### whereBetween(field, min, max)
Filters records where field value is between min and max.
**Parameters:**
- `field`: Field name
- `min`: Minimum value (inclusive)
- `max`: Maximum value (inclusive)
**Returns:** `QueryBuilder<T>`
**Example:**
```typescript
// Find users with scores between 100 and 500
const moderateUsers = await User.query().whereBetween('score', 100, 500).find();
// Find posts from last week
const lastWeek = Date.now() - 7 * 24 * 60 * 60 * 1000;
const recentPosts = await Post.query().whereBetween('createdAt', lastWeek, Date.now()).find();
```
### whereRaw(condition, parameters?)
Adds a raw WHERE condition.
**Parameters:**
- `condition`: Raw SQL-like condition string
- `parameters`: Optional parameters for the condition
**Returns:** `QueryBuilder<T>`
**Example:**
```typescript
// Complex condition
const users = await User.query()
.whereRaw('score > ? AND (registeredAt > ? OR isPremium = ?)', [100, lastWeek, true])
.find();
```
## Logical Operators
### and() / or() / not()
Combines conditions with logical operators.
**Returns:** `QueryBuilder<T>`
**Example:**
```typescript
// AND (default behavior)
const premiumActiveUsers = await User.query()
.where('isActive', true)
.and()
.where('isPremium', true)
.find();
// OR condition
const eligibleUsers = await User.query()
.where('isPremium', true)
.or()
.where('score', '>', 1000)
.find();
// NOT condition
const nonAdminUsers = await User.query().not().where('role', 'admin').find();
// Complex combinations
const complexQuery = await User.query()
.where('isActive', true)
.and()
.group((query) => query.where('isPremium', true).or().where('score', '>', 500))
.find();
```
## Sorting Methods
### orderBy(field, direction?)
Orders results by specified field.
**Parameters:**
- `field`: Field name to sort by
- `direction`: Sort direction ('asc' or 'desc', defaults to 'asc')
**Returns:** `QueryBuilder<T>`
**Example:**
```typescript
// Sort by score descending
const topUsers = await User.query().orderBy('score', 'desc').limit(10).find();
// Multiple sort criteria
const users = await User.query().orderBy('score', 'desc').orderBy('username', 'asc').find();
// Sort by date
const recentPosts = await Post.query().orderBy('createdAt', 'desc').find();
```
### orderByRaw(orderClause)
Orders results using a raw ORDER BY clause.
**Parameters:**
- `orderClause`: Raw order clause
**Returns:** `QueryBuilder<T>`
**Example:**
```typescript
const users = await User.query().orderByRaw('score DESC, RANDOM()').find();
```
## Limiting and Pagination
### limit(count)
Limits the number of results.
**Parameters:**
- `count`: Maximum number of records to return
**Returns:** `QueryBuilder<T>`
**Example:**
```typescript
// Get top 10 users
const topUsers = await User.query().orderBy('score', 'desc').limit(10).find();
```
### offset(count)
Skips a number of records.
**Parameters:**
- `count`: Number of records to skip
**Returns:** `QueryBuilder<T>`
**Example:**
```typescript
// Get users 11-20 (skip first 10)
const nextBatch = await User.query().orderBy('score', 'desc').offset(10).limit(10).find();
```
### paginate(page, perPage)
Paginates results and returns pagination info.
**Parameters:**
- `page`: Page number (1-based)
- `perPage`: Number of records per page
**Returns:** `Promise<PaginatedResult<T>>`
**Example:**
```typescript
// Get page 2 with 20 users per page
const result = await User.query().where('isActive', true).orderBy('score', 'desc').paginate(2, 20);
console.log('Users:', result.data);
console.log('Total:', result.total);
console.log('Page:', result.page);
console.log('Per page:', result.perPage);
console.log('Total pages:', result.totalPages);
console.log('Has next:', result.hasNext);
console.log('Has previous:', result.hasPrev);
```
## Relationship Methods
### with(relationships)
Eager loads relationships.
**Parameters:**
- `relationships`: Array of relationship names or dot-notation for nested relationships
**Returns:** `QueryBuilder<T>`
**Example:**
```typescript
// Load single relationship
const usersWithPosts = await User.query().with(['posts']).find();
// Load multiple relationships
const usersWithData = await User.query().with(['posts', 'profile', 'followers']).find();
// Load nested relationships
const usersWithCommentsAuthors = await User.query().with(['posts.comments.author']).find();
// Mixed relationships
const complexLoad = await User.query()
.with(['posts.comments.author', 'profile', 'followers.profile'])
.find();
```
### withCount(relationships)
Loads relationship counts without loading the actual relationships.
**Parameters:**
- `relationships`: Array of relationship names
**Returns:** `QueryBuilder<T>`
**Example:**
```typescript
const usersWithCounts = await User.query().withCount(['posts', 'followers', 'following']).find();
// Access counts
usersWithCounts.forEach((user) => {
console.log(`${user.username}: ${user.postsCount} posts, ${user.followersCount} followers`);
});
```
### whereHas(relationship, callback?)
Filters records that have related records matching criteria.
**Parameters:**
- `relationship`: Relationship name
- `callback`: Optional callback to add conditions to the relationship query
**Returns:** `QueryBuilder<T>`
**Example:**
```typescript
// Users who have posts
const usersWithPosts = await User.query().whereHas('posts').find();
// Users who have published posts
const usersWithPublishedPosts = await User.query()
.whereHas('posts', (query) => {
query.where('isPublished', true);
})
.find();
// Users who have recent posts
const usersWithRecentPosts = await User.query()
.whereHas('posts', (query) => {
query.where('createdAt', '>', Date.now() - 7 * 24 * 60 * 60 * 1000);
})
.find();
```
### whereDoesntHave(relationship)
Filters records that don't have related records.
**Parameters:**
- `relationship`: Relationship name
**Returns:** `QueryBuilder<T>`
**Example:**
```typescript
// Users without posts
const usersWithoutPosts = await User.query().whereDoesntHave('posts').find();
```
## Aggregation Methods
### count()
Returns the count of matching records.
**Returns:** `Promise<number>`
**Example:**
```typescript
// Count all active users
const activeUserCount = await User.query().where('isActive', true).count();
console.log(`Active users: ${activeUserCount}`);
```
### sum(field) / avg(field) / min(field) / max(field)
Performs aggregation operations on a field.
**Parameters:**
- `field`: Field name to aggregate
**Returns:** `Promise<number>` or `Promise<any>` for min/max
**Example:**
```typescript
// Calculate statistics
const totalScore = await User.query().sum('score');
const averageScore = await User.query().avg('score');
const highestScore = await User.query().max('score');
const lowestScore = await User.query().min('score');
console.log(`Total: ${totalScore}, Average: ${averageScore}`);
console.log(`Range: ${lowestScore} - ${highestScore}`);
// With conditions
const premiumAverage = await User.query().where('isPremium', true).avg('score');
```
## Caching Methods
### cache(ttl?)
Caches query results.
**Parameters:**
- `ttl`: Time to live in seconds (optional, uses default if not provided)
**Returns:** `QueryBuilder<T>`
**Example:**
```typescript
// Cache for default duration
const cachedUsers = await User.query().where('isActive', true).cache().find();
// Cache for 10 minutes
const cachedPosts = await Post.query().where('isPublished', true).cache(600).find();
```
### fresh()
Forces a fresh query, bypassing cache.
**Returns:** `QueryBuilder<T>`
**Example:**
```typescript
// Always fetch fresh data
const freshUsers = await User.query().where('isActive', true).fresh().find();
```
## Execution Methods
### find()
Executes the query and returns all matching records.
**Returns:** `Promise<T[]>`
**Example:**
```typescript
const users = await User.query().where('isActive', true).orderBy('score', 'desc').find();
```
### findOne() / first()
Executes the query and returns the first matching record.
**Returns:** `Promise<T | null>`
**Example:**
```typescript
// Find the highest scoring user
const topUser = await User.query().orderBy('score', 'desc').findOne();
// Find specific user
const user = await User.query().where('username', 'alice').first();
```
### get()
Alias for `find()`.
**Returns:** `Promise<T[]>`
## Advanced Methods
### distinct(field?)
Returns distinct values.
**Parameters:**
- `field`: Optional field to get distinct values for
**Returns:** `QueryBuilder<T>`
**Example:**
```typescript
// Get users with distinct emails
const uniqueUsers = await User.query().distinct('email').find();
// Get all distinct tags from posts
const uniqueTags = await Post.query().distinct('tags').find();
```
### groupBy(field)
Groups results by field.
**Parameters:**
- `field`: Field to group by
**Returns:** `QueryBuilder<T>`
**Example:**
```typescript
// Group users by registration date
const usersByDate = await User.query().groupBy('registeredAt').withCount(['posts']).find();
```
### having(field, operator, value)
Adds HAVING condition (used with groupBy).
**Parameters:**
- `field`: Field name
- `operator`: Comparison operator
- `value`: Value to compare
**Returns:** `QueryBuilder<T>`
**Example:**
```typescript
// Find dates with more than 10 user registrations
const busyDays = await User.query().groupBy('registeredAt').having('COUNT(*)', '>', 10).find();
```
## Query Inspection
### toSQL()
Returns the SQL representation of the query.
**Returns:** `string`
**Example:**
```typescript
const query = User.query().where('isActive', true).orderBy('score', 'desc').limit(10);
console.log('SQL:', query.toSQL());
```
### getParameters()
Returns the parameters for the query.
**Returns:** `any[]`
**Example:**
```typescript
const query = User.query().where('score', '>', 100);
console.log('Parameters:', query.getParameters());
```
### explain()
Returns the query execution plan.
**Returns:** `Promise<QueryPlan>`
**Example:**
```typescript
const plan = await User.query().where('isActive', true).explain();
console.log('Query plan:', plan);
```
## Type Definitions
### QueryOperator
```typescript
type QueryOperator =
| 'eq'
| '='
| 'ne'
| '!='
| '<>'
| 'gt'
| '>'
| 'gte'
| '>='
| 'lt'
| '<'
| 'lte'
| '<='
| 'in'
| 'not in'
| 'like'
| 'not like'
| 'regex'
| 'is null'
| 'is not null'
| 'includes'
| 'includes any'
| 'includes all';
```
### PaginatedResult
```typescript
interface PaginatedResult<T> {
data: T[];
total: number;
page: number;
perPage: number;
totalPages: number;
hasNext: boolean;
hasPrev: boolean;
firstPage: number;
lastPage: number;
}
```
### QueryPlan
```typescript
interface QueryPlan {
estimatedCost: number;
estimatedRows: number;
indexesUsed: string[];
operations: QueryOperation[];
warnings: string[];
}
interface QueryOperation {
type: string;
description: string;
cost: number;
}
```
## Complex Query Examples
### Advanced Filtering
```typescript
// Complex user search
const searchResults = await User.query()
.where('isActive', true)
.and()
.group((query) =>
query
.where('username', 'like', `%${searchTerm}%`)
.or()
.where('email', 'like', `%${searchTerm}%`)
.or()
.where('bio', 'like', `%${searchTerm}%`),
)
.and()
.group((query) => query.where('isPremium', true).or().where('score', '>', 500))
.orderBy('score', 'desc')
.with(['profile', 'posts.comments'])
.paginate(page, 20);
```
### Analytics Query
```typescript
// User activity analytics
const analytics = await User.query()
.where('registeredAt', '>', startDate)
.where('registeredAt', '<', endDate)
.whereHas('posts', (query) => {
query.where('isPublished', true);
})
.withCount(['posts', 'comments', 'followers'])
.orderBy('score', 'desc')
.cache(300) // Cache for 5 minutes
.find();
// Process analytics data
const stats = {
totalUsers: analytics.length,
averageScore: analytics.reduce((sum, user) => sum + user.score, 0) / analytics.length,
totalPosts: analytics.reduce((sum, user) => sum + user.postsCount, 0),
totalComments: analytics.reduce((sum, user) => sum + user.commentsCount, 0),
};
```
### Dashboard Query
```typescript
async function getDashboardData(userId: string) {
// Multiple optimized queries
const [userStats, recentPosts, topComments, followingActivity] = await Promise.all([
// User statistics
User.query()
.where('id', userId)
.withCount(['posts', 'comments', 'followers', 'following'])
.cache(60) // Cache for 1 minute
.first(),
// Recent posts
Post.query()
.where('authorId', userId)
.orderBy('createdAt', 'desc')
.limit(5)
.with(['comments.author'])
.find(),
// Top comments by user
Comment.query()
.where('authorId', userId)
.orderBy('likeCount', 'desc')
.limit(10)
.with(['post.author'])
.find(),
// Activity from people user follows
Post.query()
.whereHas('author', (query) => {
query.whereHas('followers', (followQuery) => {
followQuery.where('followerId', userId);
});
})
.orderBy('createdAt', 'desc')
.limit(20)
.with(['author', 'comments'])
.find(),
]);
return {
userStats,
recentPosts,
topComments,
followingActivity,
};
}
```
The QueryBuilder provides a powerful, type-safe way to construct complex database queries with support for relationships, caching, pagination, and advanced filtering options.

View File

@ -0,0 +1,734 @@
---
sidebar_position: 3
---
# Code Guidelines
This document outlines the coding standards, best practices, and architectural principles for contributing to DebrosFramework.
## 🎯 Core Principles
### 1. Developer Experience First
Every API decision should prioritize developer experience:
- **Intuitive naming** - Use clear, descriptive names
- **Consistent patterns** - Follow established conventions
- **Helpful errors** - Provide actionable error messages
- **Complete TypeScript** - Full type safety and IntelliSense
### 2. Performance by Default
Optimize for common use cases:
- **Lazy loading** - Load data only when needed
- **Automatic caching** - Cache frequently accessed data
- **Efficient queries** - Optimize database operations
- **Memory management** - Clean up resources properly
### 3. Scalability Built-in
Design for applications with millions of users:
- **Automatic sharding** - Distribute data effectively
- **Parallel processing** - Execute operations concurrently
- **Resource optimization** - Use resources efficiently
- **Graceful degradation** - Handle failures elegantly
## 📝 TypeScript Standards
### Type Safety Requirements
All code must be fully typed with strict TypeScript:
```typescript
// ✅ Good - Explicit types
interface UserCreateData {
username: string;
email: string;
bio?: string;
}
async function createUser(data: UserCreateData): Promise<User> {
// Implementation
}
// ❌ Bad - Using any
async function createUser(data: any): Promise<any> {
// Implementation
}
```
### Interface Design
Use interfaces for all public APIs:
```typescript
// ✅ Good - Clear interface definition
interface QueryOptions {
limit?: number;
offset?: number;
orderBy?: OrderByClause[];
with?: string[];
cache?: boolean | number;
}
// ✅ Good - Generic interfaces
interface PaginatedResult<T> {
data: T[];
total: number;
page: number;
perPage: number;
hasMore: boolean;
}
```
### Error Handling
Use typed error classes with helpful messages:
```typescript
// ✅ Good - Specific error types
export class ValidationError extends DebrosFrameworkError {
constructor(
public field: string,
public value: any,
public constraint: string,
message?: string,
) {
super(message || `Validation failed for field '${field}': ${constraint}`, 'VALIDATION_ERROR');
}
}
// ✅ Good - Error usage
throw new ValidationError('email', 'invalid-email', 'must be valid email format');
```
### Generic Programming
Use generics for reusable components:
```typescript
// ✅ Good - Generic model operations
abstract class BaseModel {
static async create<T extends BaseModel>(
this: ModelConstructor<T>,
data: Partial<T>,
): Promise<T> {
// Implementation
}
static query<T extends BaseModel>(this: ModelConstructor<T>): QueryBuilder<T> {
// Implementation
}
}
```
## 🏗️ Architecture Patterns
### Decorator Pattern
Use decorators consistently for metadata:
```typescript
// ✅ Good - Consistent decorator usage
@Model({
scope: 'global',
type: 'docstore',
sharding: { strategy: 'hash', count: 4, key: 'id' },
})
export class User extends BaseModel {
@Field({
type: 'string',
required: true,
unique: true,
validate: (value: string) => value.length >= 3,
})
username: string;
@HasMany(() => Post, 'userId')
posts: Post[];
}
```
### Service Pattern
Use dependency injection for services:
```typescript
// ✅ Good - Service injection
export class DatabaseManager {
constructor(
private orbitDBService: FrameworkOrbitDBService,
private shardManager: ShardManager,
private configManager: ConfigManager,
) {}
async getDatabaseForModel<T extends BaseModel>(
modelClass: ModelConstructor<T>,
userId?: string,
): Promise<Database> {
// Implementation
}
}
```
### Builder Pattern
Use builders for complex configuration:
```typescript
// ✅ Good - Fluent builder API
const migration = createMigration('add_user_profiles', '1.1.0')
.addField('User', 'profilePicture', { type: 'string', required: false })
.addField('User', 'bio', { type: 'string', required: false })
.transformData('User', (user) => ({
...user,
displayName: user.username || 'Anonymous',
}))
.addValidator('check_profile_data', async (context) => {
// Validation logic
})
.build();
```
## 🔄 Async/Await Patterns
### Promise Handling
Always use async/await instead of Promise chains:
```typescript
// ✅ Good - async/await
async function getUserWithPosts(userId: string): Promise<User> {
const user = await User.findById(userId);
if (!user) {
throw new NotFoundError('User', userId);
}
const posts = await Post.query().where('userId', userId).orderBy('createdAt', 'desc').find();
user.posts = posts;
return user;
}
// ❌ Bad - Promise chains
function getUserWithPosts(userId: string): Promise<User> {
return User.findById(userId).then((user) => {
if (!user) {
throw new NotFoundError('User', userId);
}
return Post.query()
.where('userId', userId)
.orderBy('createdAt', 'desc')
.find()
.then((posts) => {
user.posts = posts;
return user;
});
});
}
```
### Error Propagation
Let errors bubble up with proper context:
```typescript
// ✅ Good - Error context
async function createUserWithProfile(userData: UserCreateData): Promise<User> {
try {
const user = await User.create(userData);
try {
await UserProfile.create({
userId: user.id,
displayName: userData.username,
});
} catch (error) {
// Clean up user if profile creation fails
await user.delete();
throw new OperationError('Failed to create user profile', 'USER_PROFILE_CREATION_FAILED', {
userId: user.id,
originalError: error,
});
}
return user;
} catch (error) {
if (error instanceof ValidationError) {
throw error; // Re-throw validation errors as-is
}
throw new OperationError('Failed to create user', 'USER_CREATION_FAILED', {
userData,
originalError: error,
});
}
}
```
## 🧪 Testing Standards
### Unit Test Structure
Use consistent test structure:
```typescript
// ✅ Good - Clear test structure
describe('User Model', () => {
beforeEach(async () => {
await setupTestDatabase();
});
afterEach(async () => {
await cleanupTestDatabase();
});
describe('create', () => {
it('should create user with valid data', async () => {
// Arrange
const userData = {
username: 'testuser',
email: 'test@example.com',
};
// Act
const user = await User.create(userData);
// Assert
expect(user).toBeDefined();
expect(user.username).toBe(userData.username);
expect(user.email).toBe(userData.email);
expect(user.id).toBeDefined();
});
it('should throw ValidationError for invalid email', async () => {
// Arrange
const userData = {
username: 'testuser',
email: 'invalid-email',
};
// Act & Assert
await expect(User.create(userData)).rejects.toThrow(ValidationError);
});
});
describe('relationships', () => {
it('should load posts relationship', async () => {
// Test relationship loading
});
});
});
```
### Integration Test Patterns
Test real-world scenarios:
```typescript
// ✅ Good - Integration test
describe('Blog Scenario Integration', () => {
let framework: DebrosFramework;
beforeAll(async () => {
framework = await setupFrameworkForTesting();
});
afterAll(async () => {
await framework.stop();
});
it('should handle complete blog workflow', async () => {
// Create user
const user = await User.create({
username: 'blogger',
email: 'blogger@example.com',
});
// Create post
const post = await Post.create({
title: 'Test Post',
content: 'Test content',
userId: user.id,
});
// Add comment
const comment = await Comment.create({
content: 'Great post!',
postId: post.id,
authorId: user.id,
});
// Verify relationships
const postWithComments = await Post.query()
.where('id', post.id)
.with(['comments.author'])
.findOne();
expect(postWithComments).toBeDefined();
expect(postWithComments!.comments).toHaveLength(1);
expect(postWithComments!.comments[0].author.username).toBe('blogger');
});
});
```
## 📊 Performance Guidelines
### Query Optimization
Write efficient queries:
```typescript
// ✅ Good - Optimized query
const recentPosts = await Post.query()
.where('publishedAt', '>', Date.now() - 7 * 24 * 60 * 60 * 1000)
.where('isPublished', true)
.with(['author']) // Eager load to avoid N+1
.orderBy('publishedAt', 'desc')
.limit(20)
.cache(300) // Cache for 5 minutes
.find();
// ❌ Bad - Inefficient query
const allPosts = await Post.query().find(); // Loads everything
const recentPosts = allPosts
.filter((p) => p.publishedAt > Date.now() - 7 * 24 * 60 * 60 * 1000)
.filter((p) => p.isPublished)
.slice(0, 20);
```
### Memory Management
Clean up resources properly:
```typescript
// ✅ Good - Resource cleanup
export class QueryCache {
private cache = new Map<string, CacheEntry>();
private cleanupInterval: NodeJS.Timeout;
constructor(private ttl: number = 300000) {
this.cleanupInterval = setInterval(() => {
this.cleanup();
}, this.ttl / 2);
}
async stop(): Promise<void> {
if (this.cleanupInterval) {
clearInterval(this.cleanupInterval);
}
this.cache.clear();
}
private cleanup(): void {
const now = Date.now();
for (const [key, entry] of this.cache.entries()) {
if (entry.expiresAt < now) {
this.cache.delete(key);
}
}
}
}
```
### Async Performance
Use Promise.all for parallel operations:
```typescript
// ✅ Good - Parallel execution
async function getUserDashboardData(userId: string): Promise<DashboardData> {
const [user, recentPosts, stats, notifications] = await Promise.all([
User.findById(userId),
Post.query().where('userId', userId).limit(5).find(),
getUserStats(userId),
getRecentNotifications(userId),
]);
return {
user,
recentPosts,
stats,
notifications,
};
}
// ❌ Bad - Sequential execution
async function getUserDashboardData(userId: string): Promise<DashboardData> {
const user = await User.findById(userId);
const recentPosts = await Post.query().where('userId', userId).limit(5).find();
const stats = await getUserStats(userId);
const notifications = await getRecentNotifications(userId);
return {
user,
recentPosts,
stats,
notifications,
};
}
```
## 🔧 Code Organization
### File Structure
Organize code logically:
```
src/framework/
├── core/ # Core framework components
│ ├── ConfigManager.ts
│ ├── DatabaseManager.ts
│ └── ModelRegistry.ts
├── models/ # Model system
│ ├── BaseModel.ts
│ └── decorators/
│ ├── Field.ts
│ ├── Model.ts
│ ├── relationships.ts
│ └── hooks.ts
├── query/ # Query system
│ ├── QueryBuilder.ts
│ ├── QueryExecutor.ts
│ └── QueryOptimizer.ts
└── types/ # Type definitions
├── framework.ts
├── models.ts
└── queries.ts
```
### Import Organization
Use consistent import patterns:
```typescript
// ✅ Good - Organized imports
// Node.js built-ins
import { EventEmitter } from 'events';
import { promisify } from 'util';
// External packages
import { Database } from '@orbitdb/core';
import { CID } from 'multiformats';
// Framework internals
import { BaseModel } from '../models/BaseModel';
import { ConfigManager } from '../core/ConfigManager';
import { DatabaseManager } from '../core/DatabaseManager';
// Types
import type { ModelConfig, FieldConfig } from '../types/models';
import type { QueryOptions, QueryResult } from '../types/queries';
```
### Export Patterns
Use consistent export patterns:
```typescript
// ✅ Good - Clear exports
// Main class export
export class QueryBuilder<T extends BaseModel> {
// Implementation
}
// Type exports
export type { QueryOptions, QueryResult, WhereClause, OrderByClause };
// Utility exports
export { buildWhereClause, optimizeQuery, validateQueryOptions };
// Default export for main functionality
export default QueryBuilder;
```
## 📚 Documentation Standards
### JSDoc Comments
Document all public APIs:
````typescript
/**
* Creates a new model instance with the provided data.
*
* @template T - The model type extending BaseModel
* @param data - The data to create the model with
* @param options - Optional creation options
* @returns Promise resolving to the created model instance
*
* @throws {ValidationError} When data validation fails
* @throws {DatabaseError} When database operation fails
*
* @example
* ```typescript
* const user = await User.create({
* username: 'john',
* email: 'john@example.com'
* });
* ```
*/
static async create<T extends BaseModel>(
this: ModelConstructor<T>,
data: Partial<T>,
options?: CreateOptions
): Promise<T> {
// Implementation
}
````
### Code Comments
Add comments for complex logic:
```typescript
// ✅ Good - Explaining complex logic
private calculateShardIndex(key: string, shardCount: number): number {
// Use consistent hashing to distribute data evenly across shards
// This ensures that the same key always maps to the same shard
const hash = this.hashFunction(key);
// Use modulo to map hash to shard index
// Add 1 to avoid negative numbers with certain hash functions
return Math.abs(hash) % shardCount;
}
// ✅ Good - Explaining business logic
async ensureUserDatabaseExists(userId: string): Promise<Database> {
// Check if user database already exists in cache
const existingDb = this.userDatabases.get(userId);
if (existingDb) {
return existingDb;
}
// Create new user database with user-specific configuration
// This provides data isolation and improved performance
const database = await this.createUserDatabase(userId);
// Cache the database for future use
this.userDatabases.set(userId, database);
return database;
}
```
## ⚡ Performance Monitoring
### Metrics Collection
Add metrics to important operations:
```typescript
// ✅ Good - Performance monitoring
export class QueryExecutor {
private metrics = new Map<string, PerformanceMetric>();
async executeQuery<T>(query: QueryBuilder<T>): Promise<QueryResult<T>> {
const startTime = Date.now();
const queryKey = query.toString();
try {
const result = await this.internalExecuteQuery(query);
// Record successful execution
this.recordMetric(queryKey, Date.now() - startTime, true);
return result;
} catch (error) {
// Record failed execution
this.recordMetric(queryKey, Date.now() - startTime, false);
throw error;
}
}
private recordMetric(queryKey: string, duration: number, success: boolean): void {
const existing = this.metrics.get(queryKey) || {
count: 0,
totalDuration: 0,
successCount: 0,
averageDuration: 0,
};
existing.count++;
existing.totalDuration += duration;
if (success) existing.successCount++;
existing.averageDuration = existing.totalDuration / existing.count;
this.metrics.set(queryKey, existing);
}
}
```
## 🔒 Security Considerations
### Input Validation
Validate all inputs thoroughly:
```typescript
// ✅ Good - Input validation
export class UserService {
async createUser(userData: UserCreateData): Promise<User> {
// Validate required fields
if (!userData.username || typeof userData.username !== 'string') {
throw new ValidationError('username', userData.username, 'required string');
}
// Sanitize username
const sanitizedUsername = userData.username.trim().toLowerCase();
// Check length constraints
if (sanitizedUsername.length < 3 || sanitizedUsername.length > 20) {
throw new ValidationError('username', sanitizedUsername, 'length between 3-20');
}
// Check for valid characters
if (!/^[a-zA-Z0-9_]+$/.test(sanitizedUsername)) {
throw new ValidationError('username', sanitizedUsername, 'alphanumeric and underscore only');
}
// Check uniqueness
const existingUser = await User.findOne({ username: sanitizedUsername });
if (existingUser) {
throw new ConflictError('Username already exists');
}
return User.create({
...userData,
username: sanitizedUsername,
});
}
}
```
### Error Information
Don't leak sensitive information in errors:
```typescript
// ✅ Good - Safe error messages
catch (error) {
if (error instanceof DatabaseConnectionError) {
// Don't expose internal connection details
throw new OperationError(
'Database operation failed',
'DATABASE_ERROR',
{ operation: 'create_user' } // Safe context only
);
}
throw error;
}
// ❌ Bad - Leaking sensitive info
catch (error) {
throw new Error(`Database connection failed: ${error.message} at ${error.stack}`);
}
```
---
These guidelines help ensure that DebrosFramework maintains high code quality, performance, and developer experience. When in doubt, prioritize clarity, type safety, and developer experience.
**Next:** Check out our [Testing Guide](./testing-guide) to learn about writing comprehensive tests.

View File

@ -0,0 +1,475 @@
---
sidebar_position: 2
---
# Development Setup
This guide will help you set up your development environment for contributing to DebrosFramework.
## 🔧 Prerequisites
### Required Software
| Software | Version | Purpose |
| -------------- | ------- | --------------------------- |
| **Node.js** | 18.0+ | Runtime environment |
| **pnpm** | Latest | Package manager (preferred) |
| **Git** | Latest | Version control |
| **Docker** | Latest | Integration testing |
| **TypeScript** | 5.0+ | Development language |
### Optional Tools
- **VS Code** - Recommended editor with excellent TypeScript support
- **Docker Desktop** - GUI for Docker management
- **Gitea CLI** (if available) - Command-line interface for our Gitea instance
## 🚀 Environment Setup
### 1. Repository Access
#### Create Gitea Account
1. Visit https://git.debros.io
2. Click "Sign Up" to create an account
3. Verify your email address
4. Request access to the DeBros organization (contact maintainers)
#### Fork and Clone
```bash
# Fork the repository through Gitea web interface
# Then clone your fork
git clone https://git.debros.io/DeBros/network.git
cd network
# Add upstream remote
git remote add upstream https://git.debros.io/DeBros/network.git
# Verify remotes
git remote -v
# origin https://git.debros.io/DeBros/network.git (fetch)
# origin https://git.debros.io/DeBros/network.git (push)
# upstream https://git.debros.io/DeBros/network.git (fetch)
# upstream https://git.debros.io/DeBros/network.git (push)
```
### 2. Project Setup
#### Install Dependencies
```bash
# Install pnpm if not already installed
npm install -g pnpm
# Install project dependencies
pnpm install
# Install global development tools
pnpm install -g tsx ts-node
```
#### Verify Installation
```bash
# Check versions
node --version # Should be 18.0+
pnpm --version # Should be latest
tsc --version # Should be 5.0+
# Check project setup
pnpm run build # Should complete without errors
```
### 3. IDE Configuration
#### VS Code Setup
Install recommended extensions:
```bash
# Install VS Code extensions
code --install-extension ms-vscode.vscode-typescript-next
code --install-extension esbenp.prettier-vscode
code --install-extension ms-vscode.vscode-eslint
code --install-extension bradlc.vscode-tailwindcss
code --install-extension ms-vscode.vscode-json
```
Create `.vscode/settings.json`:
```json
{
"typescript.preferences.includePackageJsonAutoImports": "auto",
"typescript.suggest.autoImports": true,
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"typescript.preferences.importModuleSpecifier": "relative",
"files.exclude": {
"**/node_modules": true,
"**/dist": true,
"**/.git": true
}
}
```
#### TypeScript Configuration
The project includes proper TypeScript configuration in `tsconfig.json`:
```json
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": true,
"outDir": "./dist",
"rootDir": "./src"
}
}
```
## 🧪 Development Workflow
### Running the Framework
#### Basic Build and Test
```bash
# Clean build
pnpm run clean
pnpm run build
# Run unit tests
pnpm run test:unit
# Run integration tests (requires Docker)
pnpm run test:real
# Run specific blog integration test
pnpm run test:blog-integration
```
#### Development Commands
```bash
# Watch mode for development
pnpm run dev
# Linting and formatting
pnpm run lint # Check for lint errors
pnpm run lint:fix # Fix auto-fixable lint errors
pnpm run format # Format code with Prettier
# Clean up
pnpm run clean # Remove build artifacts
```
### Testing Setup
#### Unit Tests
Unit tests use Jest and are located in `tests/unit/`:
```bash
# Run all unit tests
pnpm run test:unit
# Run specific test file
npx jest tests/unit/framework/core/ConfigManager.test.ts
# Run tests in watch mode
npx jest --watch tests/unit/
```
#### Integration Tests
Integration tests use Docker to create real IPFS/OrbitDB environments:
```bash
# Ensure Docker is running
docker --version
# Run full integration test suite
pnpm run test:real
# This will:
# 1. Build Docker containers
# 2. Start IPFS bootstrap node
# 3. Start multiple framework instances
# 4. Run real-world scenarios
# 5. Tear down containers
```
#### Test Structure
```
tests/
├── unit/ # Unit tests
│ ├── framework/ # Framework component tests
│ └── shared/ # Shared test utilities
└── real-integration/ # Integration tests
└── blog-scenario/ # Blog application test scenario
├── docker/ # Docker configuration
├── scenarios/ # Test scenarios
└── models/ # Test models
```
### Docker Development
#### Docker Setup for Testing
The integration tests require Docker. Make sure you have:
1. **Docker Desktop** installed and running
2. **Docker Compose** available (included with Docker Desktop)
3. **Sufficient memory** allocated to Docker (4GB+ recommended)
#### Docker Commands
```bash
# Build test containers
docker-compose -f tests/real-integration/blog-scenario/docker/docker-compose.blog.yml build
# Run integration tests
pnpm run test:real
# Clean up Docker resources
docker system prune -f
```
## 🔄 Git Workflow
### Branch Strategy
We use a feature branch workflow:
```bash
# Start from main branch
git checkout main
git pull upstream main
# Create feature branch
git checkout -b feature/your-feature-name
# Make changes, commit, and push
git add .
git commit -m "feat: add new feature"
git push origin feature/your-feature-name
```
### Pull Request Process
1. **Create Pull Request** in Gitea web interface
2. **Fill out template** with description and testing notes
3. **Request review** from maintainers
4. **Address feedback** if any
5. **Merge** once approved
## 🛠️ Development Tools
### Code Quality Tools
#### ESLint Configuration
The project uses ESLint for code quality:
```bash
# Check for issues
pnpm run lint
# Fix auto-fixable issues
pnpm run lint:fix
```
#### Prettier Configuration
Prettier handles code formatting:
```bash
# Format all files
pnpm run format
# Format specific files
npx prettier --write "src/**/*.ts"
```
#### Husky Git Hooks
The project includes pre-commit hooks:
- **Pre-commit**: Runs lint-staged to format staged files
- **Pre-push**: Runs basic tests to prevent broken code
### Package Scripts Reference
```json
{
"scripts": {
"build": "tsc && tsc-esm-fix --outDir=./dist/esm",
"dev": "tsc -w",
"clean": "rimraf dist",
"lint": "npx eslint src",
"format": "prettier --write \"**/*.{ts,js,json,md}\"",
"lint:fix": "npx eslint src --fix",
"test:unit": "jest tests/unit",
"test:blog-integration": "tsx tests/real-integration/blog-scenario/scenarios/BlogTestRunner.ts",
"test:real": "docker-compose -f tests/real-integration/blog-scenario/docker/docker-compose.blog.yml up --build --abort-on-container-exit",
"prepublishOnly": "npm run clean && npm run build"
}
}
```
## 🔍 Debugging
### Framework Debugging
#### Enable Debug Logging
```typescript
// In your test or development code
const framework = new DebrosFramework({
monitoring: {
logLevel: 'debug',
enableMetrics: true,
},
});
```
#### VS Code Debugging
Create `.vscode/launch.json`:
```json
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Unit Tests",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"args": ["--runInBand", "${file}"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"env": {
"NODE_ENV": "test"
}
},
{
"name": "Debug Integration Test",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/node_modules/.bin/tsx",
"args": ["tests/real-integration/blog-scenario/scenarios/BlogTestRunner.ts"],
"console": "integratedTerminal",
"env": {
"NODE_ENV": "test"
}
}
]
}
```
### Common Issues
#### Node.js Version Issues
```bash
# Check Node.js version
node --version
# If using nvm, switch to correct version
nvm use 18
nvm install 18.19.0
nvm alias default 18.19.0
```
#### Docker Issues
```bash
# Check Docker status
docker --version
docker-compose --version
# Clean Docker cache if tests fail
docker system prune -f
docker volume prune -f
```
#### TypeScript Issues
```bash
# Clear TypeScript cache
npx tsc --build --clean
# Rebuild project
pnpm run clean
pnpm run build
```
## 📚 Additional Resources
### Learning Resources
- **[IPFS Documentation](https://docs.ipfs.io/)** - Understanding IPFS concepts
- **[OrbitDB Guide](https://orbitdb.org/getting-started/)** - OrbitDB basics
- **[libp2p Concepts](https://docs.libp2p.io/concepts/)** - Peer-to-peer networking
- **[TypeScript Handbook](https://www.typescriptlang.org/docs/)** - TypeScript reference
### Community Resources
- **Gitea Repository**: https://git.debros.io/DeBros/network
- **Documentation**: This documentation site
- **Discord** (if available): Community chat
- **Email**: Contact maintainers for access and questions
---
## ✅ Setup Verification
Run this checklist to verify your setup:
```bash
# 1. Check Node.js version
node --version # Should be 18.0+
# 2. Check package manager
pnpm --version # Should be latest
# 3. Install dependencies
pnpm install # Should complete without errors
# 4. Build project
pnpm run build # Should complete without errors
# 5. Run linting
pnpm run lint # Should pass with no errors
# 6. Run unit tests
pnpm run test:unit # Should pass all tests
# 7. Check Docker (optional, for integration tests)
docker --version # Should show Docker version
pnpm run test:real # Should run integration tests
```
If all steps pass, you're ready to contribute! 🎉
---
**Next Steps:**
- Read our **[Code Guidelines](./code-guidelines)** to understand coding standards
- Check out **[Testing Guide](./testing-guide)** to learn about writing tests
- Browse existing issues in Gitea to find something to work on

View File

@ -0,0 +1,214 @@
---
sidebar_position: 1
---
# Contributing to DebrosFramework
Welcome to the DebrosFramework contributor community! We're excited to have you help build the future of decentralized application development.
## 🌟 Why Contribute?
DebrosFramework is an ambitious project that aims to make decentralized application development as simple as traditional web development. Your contributions help:
- **Advance decentralized technology** - Make dApps more accessible to developers
- **Build better tools** - Create powerful abstractions over IPFS and OrbitDB
- **Shape the future** - Influence how decentralized applications are built
- **Learn cutting-edge tech** - Work with the latest in distributed systems
- **Join a community** - Connect with like-minded developers
## 🚀 Development Status
**Current Version**: 0.5.0-beta
**Status**: Active Development - Beta Release
DebrosFramework is in active beta development. The core architecture is not stable, but we're continuously improving APIs, adding features, and optimizing performance. This is an excellent time to contribute as your input can significantly shape the framework's direction.
### What's Ready for Contribution
**Core Framework** - Stable architecture, ready for enhancements
**Model System** - Decorator-based models with validation
**Query Builder** - Rich querying with optimization
**Relationship System** - Complex data relationships
**Sharding** - Automatic data distribution
**Migration System** - Schema evolution tools
**Documentation** - Comprehensive guides and examples
### What's Coming Next
🔄 **Performance Optimization** - Query caching and execution improvements
🔄 **Advanced Features** - Real-time subscriptions and event systems
🔄 **Developer Experience** - Better tooling and debugging
🔄 **Production Ready** - Stability and performance for production use
## 🏗️ Repository Information
### Self-Hosted Git Repository
We use a **self-hosted Gitea instance** instead of GitHub:
**Repository URL**: https://git.debros.io/DeBros/network
**Why Gitea?**
- **Decentralization aligned** - Fits our philosophy of decentralized systems
- **Full control** - Complete control over our development infrastructure
- **Privacy focused** - No external dependencies for sensitive development data
- **Community owned** - Aligns with our open-source, community-driven approach
### Getting Repository Access
1. **Create an account** at https://git.debros.io
2. **Request access** by contacting the maintainers
3. **Fork the repository** to your account
4. **Clone your fork** locally
```bash
git clone https://git.debros.io/DeBros/network.git
cd network
```
## 🤝 How to Contribute
### Types of Contributions Welcome
| Type | Description | Skill Level | Time Commitment |
| ----------------------- | ------------------------------ | --------------------- | --------------- |
| 🐛 **Bug Reports** | Find and report issues | Beginner | Low |
| 📖 **Documentation** | Improve guides and examples | Beginner-Intermediate | Low-Medium |
| ✨ **Feature Requests** | Suggest new capabilities | Any | Low |
| 🧪 **Testing** | Write tests and test scenarios | Intermediate | Medium |
| 🔧 **Bug Fixes** | Fix reported issues | Intermediate | Medium |
| ⚡ **Performance** | Optimize existing code | Advanced | Medium-High |
| 🚀 **New Features** | Implement new functionality | Advanced | High |
| 🏗️ **Architecture** | Design system improvements | Expert | High |
### Contribution Areas
#### 🎯 High Priority Areas
1. **Integration Tests** - Real-world scenario testing
2. **Performance Optimization** - Query execution and caching
3. **Developer Experience** - Better error messages and debugging
4. **Documentation** - More examples and use cases
5. **Type Safety** - Improved TypeScript definitions
#### 🔥 Hot Topics
- **Real-time Features** - PubSub improvements and real-time data sync
- **Migration Tools** - Better schema evolution and data transformation
- **Query Optimization** - Smarter query planning and execution
- **Monitoring** - Performance metrics and health checking
- **CLI Tools** - Development and deployment tooling
## 🛠️ Technical Overview
### Architecture Understanding
Before contributing code, familiarize yourself with the framework architecture:
```
DebrosFramework/
├── Core Layer (ConfigManager, DatabaseManager)
├── Model Layer (BaseModel, Decorators, Validation)
├── Query Layer (QueryBuilder, QueryExecutor, Optimization)
├── Relationship Layer (RelationshipManager, LazyLoader)
├── Sharding Layer (ShardManager, Distribution)
├── Migration Layer (MigrationManager, MigrationBuilder)
├── Feature Layer (PinningManager, PubSubManager)
└── Service Layer (OrbitDBService, IPFSService)
```
### Key Technologies
- **TypeScript** - Primary development language
- **OrbitDB** - Distributed database layer
- **IPFS/Helia** - Distributed storage layer
- **libp2p** - Peer-to-peer networking
- **Docker** - Containerization for testing
- **Jest** - Unit testing framework
- **Prettier/ESLint** - Code formatting and linting
### Development Philosophy
1. **Developer Experience First** - APIs should be intuitive and well-documented
2. **Type Safety** - Comprehensive TypeScript support throughout
3. **Performance by Default** - Optimize common use cases automatically
4. **Flexibility** - Support diverse application patterns
5. **Reliability** - Robust error handling and recovery
6. **Scalability** - Design for applications with millions of users
## 📋 Getting Started Checklist
Before making your first contribution:
- [ ] Read this contributor guide completely
- [ ] Set up your development environment
- [ ] Run the test suite successfully
- [ ] Explore the codebase and documentation
- [ ] Join our community channels
- [ ] Choose your first contribution area
- [ ] Check existing issues and discussions
## 🔗 Quick Links
- **[Development Setup](./development-setup)** - Get your environment ready
- **[Code Guidelines](./code-guidelines)** - Coding standards and best practices
- **[Testing Guide](./testing-guide)** - How to write and run tests
- **[Documentation Guide](./documentation-guide)** - Contributing to docs
- **[Release Process](./release-process)** - How we ship new versions
- **[Community](./community)** - Connect with other contributors
## 💡 First Time Contributors
New to open source or DebrosFramework? Start here:
1. **Good First Issues** - Look for issues tagged `good-first-issue` in our Gitea repository
2. **Documentation** - Help improve our guides and examples
3. **Testing** - Add test cases for existing functionality
4. **Examples** - Create new usage examples and tutorials
## 🎯 Contributor Levels
### 🌱 **Beginner Contributors**
- Report bugs and suggest improvements
- Fix typos and improve documentation
- Add simple test cases
- Create usage examples
### 🌿 **Intermediate Contributors**
- Fix bugs and implement small features
- Improve existing functionality
- Write comprehensive tests
- Contribute to API design discussions
### 🌳 **Advanced Contributors**
- Implement major features
- Optimize performance-critical code
- Design architectural improvements
- Mentor other contributors
### 🏆 **Core Contributors**
- Drive technical direction
- Review and merge contributions
- Manage releases and roadmap
- Represent the project publicly
## 🏅 Recognition
Contributors are recognized through:
- **Contributor list** in repository and documentation
- **Release notes** crediting significant contributions
- **Community highlights** in announcements
- **Direct contributor access** for consistent contributors
- **Maintainer status** for exceptional long-term contributors
---
Ready to contribute? Head over to our **[Development Setup Guide](./development-setup)** to get started!
_Have questions? Join our community channels or reach out to the maintainers. We're here to help! 🚀_

View File

@ -109,6 +109,18 @@ DebrosFramework is perfect for developers who want to:
Ready to build your first decentralized application? Check out our [Getting Started Guide](./getting-started) to set up your development environment and create your first models.
## Development Status
**Current Version**: 0.5.0-beta
**Status**: Active Development - Beta Release
DebrosFramework is currently in beta and under active development. The core architecture and APIs are stabilizing, but some features may still change. We recommend using it for:
- ✅ **Development and Testing**: Perfect for building and testing decentralized applications
- ✅ **Prototyping**: Rapid prototyping of dApp concepts
- ✅ **Learning**: Understanding decentralized application architecture
- ⚠️ **Production**: Use with caution - APIs may change in future versions
## Community and Support
- 📖 [Documentation](./getting-started) - Comprehensive guides and examples

691
docs/docs/videos/index.md Normal file
View File

@ -0,0 +1,691 @@
---
sidebar_position: 6
---
# Video Tutorials
Learn Debros Network through comprehensive video tutorials. These step-by-step guides will help you master the framework from basic concepts to advanced implementations.
## 🎬 **Getting Started Series**
### 1. Introduction to Debros Network
**Duration: 15 minutes**
A complete overview of Debros Network, its architecture, and core concepts. Perfect for developers new to decentralized applications.
**What You'll Learn:**
- Framework architecture and components
- Key differences from traditional frameworks
- When to use Debros Network
- Development environment overview
```typescript
// Code examples from this video
import { DebrosFramework, BaseModel, Model, Field } from '@debros/network';
@Model({
scope: 'global',
type: 'docstore',
})
class User extends BaseModel {
@Field({ type: 'string', required: true })
username: string;
}
```
[**▶️ Watch Introduction Video**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
### 2. Setting Up Your Development Environment
**Duration: 20 minutes**
Step-by-step guide to setting up Debros Network in your development environment.
**What You'll Learn:**
- Installing dependencies
- Project structure setup
- IDE configuration
- Development tools
**Prerequisites:**
- Node.js 18+
- npm or pnpm
- TypeScript knowledge
```bash
# Commands from this video
npm create debros-app my-app
cd my-app
npm install
npm run dev
```
[**▶️ Watch Setup Video**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
### 3. Your First Debros Application
**Duration: 25 minutes**
Build your first decentralized application with user management and basic CRUD operations.
**What You'll Learn:**
- Creating models with decorators
- Database initialization
- Basic CRUD operations
- Error handling
**Project Files:**
- `models/User.ts`
- `models/Post.ts`
- `app.ts`
```typescript
// Final code from this tutorial
@Model({
scope: 'global',
type: 'docstore',
sharding: { strategy: 'hash', count: 4, key: 'id' },
})
export class User extends BaseModel {
@Field({ type: 'string', required: true, unique: true })
username: string;
@Field({ type: 'string', required: true, unique: true })
email: string;
@HasMany(() => Post, 'authorId')
posts: Post[];
}
```
[**▶️ Watch First App Video**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
## 🏗️ **Core Concepts Series**
### 4. Understanding Models and Decorators
**Duration: 30 minutes**
Deep dive into the model system, decorators, and data validation.
**Topics Covered:**
- Model configuration options
- Field types and validation
- Custom validators
- Lifecycle hooks
- Best practices
```typescript
// Advanced model example from video
@Model({
scope: 'user',
type: 'docstore',
sharding: { strategy: 'user', count: 2, key: 'userId' },
})
export class BlogPost extends BaseModel {
@Field({
type: 'string',
required: true,
minLength: 5,
maxLength: 200,
validate: (title: string) => !title.includes('spam'),
})
title: string;
@BeforeCreate()
async validatePost() {
// Custom validation logic
}
}
```
[**▶️ Watch Models Deep Dive**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
### 5. Mastering the Query System
**Duration: 35 minutes**
Complete guide to building complex queries with relationships and optimization.
**Topics Covered:**
- Query builder API
- Filtering and sorting
- Relationship loading
- Pagination
- Query optimization
- Caching strategies
```typescript
// Complex query example from video
const results = await User.query()
.where('isActive', true)
.where('score', '>', 100)
.whereHas('posts', (query) => {
query.where('isPublished', true).where('createdAt', '>', Date.now() - 30 * 24 * 60 * 60 * 1000);
})
.with(['posts.comments.author', 'profile'])
.orderBy('score', 'desc')
.cache(300)
.paginate(1, 20);
```
[**▶️ Watch Query Mastery**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
### 6. Working with Relationships
**Duration: 25 minutes**
Understanding and implementing relationships between models.
**Topics Covered:**
- Relationship types (HasMany, BelongsTo, etc.)
- Eager vs lazy loading
- Nested relationships
- Performance considerations
```typescript
// Relationship examples from video
@Model({ scope: 'global', type: 'docstore' })
export class User extends BaseModel {
@HasMany(() => Post, 'authorId')
posts: Post[];
@ManyToMany(() => User, 'followers', 'following')
followers: User[];
@HasOne(() => UserProfile, 'userId')
profile: UserProfile;
}
```
[**▶️ Watch Relationships Video**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
## 🚀 **Advanced Features Series**
### 7. Database Sharding and Scaling
**Duration: 40 minutes**
Learn how to scale your application with automatic sharding strategies.
**Topics Covered:**
- Sharding strategies
- User-scoped vs global databases
- Performance optimization
- Monitoring and metrics
```typescript
// Sharding configuration examples
@Model({
scope: 'user',
type: 'docstore',
sharding: {
strategy: 'hash',
count: 8,
key: 'userId',
},
})
export class UserData extends BaseModel {
// Model implementation
}
```
[**▶️ Watch Sharding Guide**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
### 8. Migrations and Schema Evolution
**Duration: 30 minutes**
Managing database schema changes and data migrations.
**Topics Covered:**
- Creating migrations
- Data transformations
- Rollback strategies
- Production deployment
```typescript
// Migration example from video
const migration = createMigration('add_user_profiles', '1.1.0')
.addField('User', 'profilePicture', {
type: 'string',
required: false,
})
.addField('User', 'bio', {
type: 'string',
required: false,
})
.transformData('User', (user) => ({
...user,
displayName: user.username || 'Anonymous',
}))
.build();
```
[**▶️ Watch Migrations Video**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
### 9. Real-time Features and PubSub
**Duration: 25 minutes**
Implementing real-time functionality with the built-in PubSub system.
**Topics Covered:**
- Event publishing
- Real-time subscriptions
- WebSocket integration
- Performance considerations
```typescript
// Real-time examples from video
@Model({ scope: 'global', type: 'docstore' })
export class ChatMessage extends BaseModel {
@AfterCreate()
async publishMessage() {
await this.publish('message:created', {
roomId: this.roomId,
message: this,
});
}
}
```
[**▶️ Watch Real-time Video**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
## 🛠️ **Project Tutorials**
### 10. Building a Complete Blog Application
**Duration: 60 minutes**
Build a full-featured blog application with authentication, posts, and comments.
**Features Built:**
- User authentication
- Post creation and editing
- Comment system
- User profiles
- Admin dashboard
**Final Project Structure:**
```
blog-app/
├── models/
│ ├── User.ts
│ ├── Post.ts
│ ├── Comment.ts
│ └── Category.ts
├── services/
│ ├── AuthService.ts
│ └── BlogService.ts
└── app.ts
```
[**▶️ Watch Blog Tutorial**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
### 11. Creating a Social Media Platform
**Duration: 90 minutes**
Build a decentralized social media platform with advanced features.
**Features Built:**
- User profiles and following
- Feed generation
- Real-time messaging
- Content moderation
- Analytics dashboard
**Part 1: User System and Profiles** (30 min)
[**▶️ Watch Part 1**](https://youtube.com/watch?v=VIDEO_ID_HERE)
**Part 2: Posts and Feed** (30 min)
[**▶️ Watch Part 2**](https://youtube.com/watch?v=VIDEO_ID_HERE)
**Part 3: Real-time Features** (30 min)
[**▶️ Watch Part 3**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
### 12. E-commerce Platform with Debros Network
**Duration: 75 minutes**
Build a decentralized e-commerce platform with product management and orders.
**Features Built:**
- Product catalog
- Shopping cart
- Order processing
- Inventory management
- Payment integration
**Part 1: Product Management** (25 min)
[**▶️ Watch Part 1**](https://youtube.com/watch?v=VIDEO_ID_HERE)
**Part 2: Shopping and Orders** (25 min)
[**▶️ Watch Part 2**](https://youtube.com/watch?v=VIDEO_ID_HERE)
**Part 3: Advanced Features** (25 min)
[**▶️ Watch Part 3**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
## 🔧 **Development Workflow Series**
### 13. Testing Strategies for Debros Applications
**Duration: 35 minutes**
Comprehensive testing approaches for decentralized applications.
**Topics Covered:**
- Unit testing models
- Integration testing
- Mocking strategies
- Performance testing
```typescript
// Testing example from video
describe('User Model', () => {
it('should create user with valid data', async () => {
const user = await User.create({
username: 'testuser',
email: 'test@example.com',
});
expect(user.id).toBeDefined();
expect(user.username).toBe('testuser');
});
});
```
[**▶️ Watch Testing Video**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
### 14. Deployment and Production Best Practices
**Duration: 45 minutes**
Deploy your Debros Network applications to production environments.
**Topics Covered:**
- Production configuration
- Docker containers
- Monitoring and logging
- Performance optimization
- Security considerations
```dockerfile
# Docker example from video
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]
```
[**▶️ Watch Deployment Video**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
### 15. Performance Optimization Techniques
**Duration: 40 minutes**
Advanced techniques for optimizing Debros Network applications.
**Topics Covered:**
- Query optimization
- Caching strategies
- Database indexing
- Memory management
- Profiling tools
```typescript
// Optimization examples from video
// Efficient query with proper indexing
const optimizedQuery = await User.query()
.where('isActive', true) // Indexed field
.with(['posts']) // Eager load to avoid N+1
.cache(300) // Cache frequently accessed data
.limit(50) // Reasonable limits
.find();
```
[**▶️ Watch Optimization Video**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
## 📱 **Integration Series**
### 16. Frontend Integration with React
**Duration: 50 minutes**
Integrate Debros Network with React applications for full-stack development.
**Topics Covered:**
- React hooks for Debros
- State management
- Real-time updates
- Error boundaries
```typescript
// React integration example from video
import { useDebrosQuery, useDebrosModel } from '@debros/react';
function UserProfile({ userId }: { userId: string }) {
const { user, loading, error } = useDebrosModel(User, userId, {
with: ['posts', 'profile']
});
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<h1>{user.username}</h1>
<p>Posts: {user.posts.length}</p>
</div>
);
}
```
[**▶️ Watch React Integration**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
### 17. Building APIs with Express and Debros
**Duration: 35 minutes**
Create REST APIs using Express.js with Debros Network as the backend.
**Topics Covered:**
- Express middleware
- API route design
- Authentication
- Error handling
- API documentation
```typescript
// Express API example from video
app.get('/api/users/:id', async (req, res) => {
try {
const user = await User.findById(req.params.id, {
with: ['posts'],
});
if (!user) {
return res.status(404).json({ error: 'User not found' });
}
res.json(user);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
```
[**▶️ Watch Express Integration**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
### 18. Mobile Development with React Native
**Duration: 45 minutes**
Build mobile applications using React Native and Debros Network.
**Topics Covered:**
- React Native setup
- Offline synchronization
- Mobile-specific optimizations
- Push notifications
[**▶️ Watch Mobile Development**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
## 🎓 **Masterclass Series**
### 19. Architecture Patterns and Best Practices
**Duration: 60 minutes**
Advanced architectural patterns for large-scale Debros Network applications.
**Topics Covered:**
- Domain-driven design
- CQRS patterns
- Event sourcing
- Microservices architecture
[**▶️ Watch Architecture Masterclass**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
### 20. Contributing to Debros Network
**Duration: 30 minutes**
Learn how to contribute to the Debros Network open-source project.
**Topics Covered:**
- Development setup
- Code standards
- Testing requirements
- Pull request process
[**▶️ Watch Contributing Guide**](https://youtube.com/watch?v=VIDEO_ID_HERE)
---
## 📚 **Additional Resources**
### Video Playlists
**🎬 [Complete Beginner Series](https://youtube.com/playlist?list=PLAYLIST_ID)**
Videos 1-6: Everything you need to get started
**🏗️ [Advanced Development](https://youtube.com/playlist?list=PLAYLIST_ID)**
Videos 7-12: Advanced features and patterns
**🛠️ [Project Tutorials](https://youtube.com/playlist?list=PLAYLIST_ID)**
Videos 10-12: Complete project walkthroughs
**🔧 [Production Ready](https://youtube.com/playlist?list=PLAYLIST_ID)**
Videos 13-15: Testing, deployment, and optimization
### Community Videos
**Community Showcase**
- [Building a Decentralized Chat App](https://youtube.com/watch?v=COMMUNITY_VIDEO_1)
- [E-learning Platform with Debros](https://youtube.com/watch?v=COMMUNITY_VIDEO_2)
- [IoT Data Management](https://youtube.com/watch?v=COMMUNITY_VIDEO_3)
### Interactive Learning
**🎮 [Interactive Tutorials](https://learn.debros.io)**
Hands-on coding exercises with instant feedback
**💬 [Discord Community](https://discord.gg/debros)**
Get help and discuss videos with other developers
**📖 [Workshop Materials](https://github.com/debros/workshops)**
Download code samples and workshop materials
---
## 📅 **Release Schedule**
New video tutorials are released every **Tuesday and Friday**:
- **Tuesdays**: Core concepts and feature deep-dives
- **Fridays**: Project tutorials and real-world applications
**Subscribe to our [YouTube channel](https://youtube.com/@debrosnetwork)** and enable notifications to stay updated with the latest tutorials.
## 🤝 **Request a Tutorial**
Have a specific topic you'd like covered? Request a tutorial:
- **[GitHub Discussions](https://github.com/debros/network/discussions)** - Community requests
- **[Email Us](mailto:tutorials@debros.io)** - Direct requests
- **[Discord](https://discord.gg/debros)** - Community suggestions
We prioritize tutorials based on community demand and framework updates.
---
_All videos include closed captions, downloadable code samples, and companion blog posts for reference._

View File

@ -1,12 +1,12 @@
import {themes as prismThemes} from 'prism-react-renderer';
import type {Config} from '@docusaurus/types';
import { themes as prismThemes } from 'prism-react-renderer';
import type { Config } from '@docusaurus/types';
import type * as Preset from '@docusaurus/preset-classic';
// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...)
const config: Config = {
title: 'DebrosFramework',
tagline: 'Build scalable decentralized applications with ease',
title: 'Debros Network',
tagline: 'Next-Generation Decentralized Web Framework',
favicon: 'img/favicon.ico',
// Future flags, see https://docusaurus.io/docs/api/docusaurus-config#future
@ -71,13 +71,20 @@ const config: Config = {
themeConfig: {
// Replace with your project's social card
image: 'img/docusaurus-social-card.jpg',
image: 'img/debros-social-card.jpg',
colorMode: {
defaultMode: 'dark',
disableSwitch: false,
respectPrefersColorScheme: false,
},
navbar: {
title: 'DebrosFramework',
logo: {
alt: 'DebrosFramework Logo',
src: 'img/logo.svg',
},
title: 'Debros Network',
// logo: {
// alt: 'Debros Network Logo',
// src: 'img/logo.svg',
// srcDark: 'img/logo-dark.svg',
// },
hideOnScroll: true,
items: [
{
type: 'docSidebar',
@ -91,10 +98,14 @@ const config: Config = {
position: 'left',
label: 'API Reference',
},
{to: '/blog', label: 'Blog', position: 'left'},
{
href: 'https://git.debros.io/DeBros/network',
label: 'Gitea',
position: 'right',
},
{
href: 'https://github.com/debros/network',
label: 'GitHub',
label: 'GitHub Mirror',
position: 'right',
},
],
@ -103,11 +114,23 @@ const config: Config = {
style: 'dark',
links: [
{
title: 'Docs',
title: 'Documentation',
items: [
{
label: 'Tutorial',
to: '/docs/intro',
label: 'Getting Started',
to: '/docs/getting-started',
},
{
label: 'Core Concepts',
to: '/docs/core-concepts/architecture',
},
{
label: 'API Reference',
to: '/docs/api/overview',
},
{
label: 'Contributing',
to: '/docs/contributing/overview',
},
],
},
@ -115,34 +138,34 @@ const config: Config = {
title: 'Community',
items: [
{
label: 'Stack Overflow',
href: 'https://stackoverflow.com/questions/tagged/docusaurus',
label: 'Gitea Repository',
href: 'https://git.debros.io/DeBros/network',
},
{
label: 'Discord',
href: 'https://discordapp.com/invite/docusaurus',
label: 'GitHub Mirror',
href: 'https://github.com/debros/network',
},
{
label: 'X',
href: 'https://x.com/docusaurus',
label: 'Issues & Support',
href: 'https://git.debros.io/DeBros/network/issues',
},
],
},
{
title: 'More',
title: 'Resources',
items: [
{
label: 'Blog',
to: '/blog',
label: 'Examples',
to: '/docs/examples/basic-usage',
},
{
label: 'GitHub',
href: 'https://github.com/facebook/docusaurus',
label: 'License',
href: 'https://git.debros.io/DeBros/network/src/branch/main/LICENSE',
},
],
},
],
copyright: `Copyright © ${new Date().getFullYear()} DebrosFramework. Built with Docusaurus.`,
copyright: `Copyright © ${new Date().getFullYear()} Debros Network. Empowering the decentralized web.`,
},
prism: {
theme: prismThemes.github,

View File

@ -40,6 +40,22 @@ const sidebars: SidebarsConfig = {
'examples/basic-usage',
],
},
{
type: 'category',
label: 'Video Tutorials',
items: [
'videos/index',
],
},
{
type: 'category',
label: 'Contributing',
items: [
'contributing/overview',
'contributing/development-setup',
'contributing/code-guidelines',
],
},
],
// API Reference sidebar
@ -47,9 +63,18 @@ const sidebars: SidebarsConfig = {
'api/overview',
{
type: 'category',
label: 'Framework Classes',
label: 'Core Classes',
items: [
'api/debros-framework',
'api/base-model',
'api/query-builder',
],
},
{
type: 'category',
label: 'Network API',
items: [
'api/network-api',
],
},
],

View File

@ -5,52 +5,86 @@ import styles from './styles.module.css';
type FeatureItem = {
title: string;
Svg: React.ComponentType<React.ComponentProps<'svg'>>;
icon: string;
description: ReactNode;
highlight?: boolean;
};
const FeatureList: FeatureItem[] = [
{
title: 'Easy to Use',
Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default,
title: 'Decentralized by Design',
icon: '🌐',
description: (
<>
Docusaurus was designed from the ground up to be easily installed and
used to get your website up and running quickly.
Built on <strong>OrbitDB</strong> and <strong>IPFS</strong>, DebrosFramework
creates truly decentralized applications that don't rely on centralized servers
or single points of failure.
</>
),
highlight: true,
},
{
title: 'Developer Experience First',
icon: '⚡',
description: (
<>
Full <strong>TypeScript</strong> support with intelligent auto-completion,
decorator-based models, and intuitive APIs that make building complex
applications feel effortless.
</>
),
},
{
title: 'Focus on What Matters',
Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default,
title: 'Infinite Scalability',
icon: '🚀',
description: (
<>
Docusaurus lets you focus on your docs, and we&apos;ll do the chores. Go
ahead and move your docs into the <code>docs</code> directory.
Automatic sharding, efficient queries, and built-in caching ensure your
applications can scale to millions of users without architectural changes.
</>
),
},
{
title: 'Powered by React',
Svg: require('@site/static/img/undraw_docusaurus_react.svg').default,
title: 'Zero Configuration',
icon: '🎯',
description: (
<>
Extend or customize your website layout by reusing React. Docusaurus can
be extended while reusing the same header and footer.
Start building immediately with sensible defaults. No complex setup,
no configuration files, no DevOps headachesjust pure development focus.
</>
),
},
{
title: 'Real-time Sync',
icon: '🔄',
description: (
<>
Built-in real-time synchronization across all peers. Changes propagate
instantly across the network with conflict resolution and offline support.
</>
),
},
{
title: 'Enterprise Ready',
icon: '🔒',
description: (
<>
Production-grade security, comprehensive testing, detailed documentation,
and enterprise support make DebrosFramework ready for mission-critical applications.
</>
),
},
];
function Feature({title, Svg, description}: FeatureItem) {
function Feature({title, icon, description, highlight}: FeatureItem) {
return (
<div className={clsx('col col--4')}>
<div className="text--center">
<Svg className={styles.featureSvg} role="img" />
<div className={clsx(styles.featureCard, highlight && styles.featureCardHighlight)}>
<div className={styles.featureIcon}>
<span className={styles.iconEmoji}>{icon}</span>
</div>
<div className="text--center padding-horiz--md">
<Heading as="h3">{title}</Heading>
<p>{description}</p>
<div className={styles.featureContent}>
<Heading as="h3" className={styles.featureTitle}>{title}</Heading>
<p className={styles.featureDescription}>{description}</p>
</div>
</div>
);
@ -60,7 +94,15 @@ export default function HomepageFeatures(): ReactNode {
return (
<section className={styles.features}>
<div className="container">
<div className="row">
<div className={styles.featuresHeader}>
<Heading as="h2" className={styles.featuresTitle}>
Why Choose Debros Network?
</Heading>
<p className={styles.featuresSubtitle}>
Everything you need to build the next generation of decentralized applications
</p>
</div>
<div className={styles.featuresGrid}>
{FeatureList.map((props, idx) => (
<Feature key={idx} {...props} />
))}

View File

@ -1,11 +1,191 @@
/* Features Section */
.features {
display: flex;
align-items: center;
padding: 2rem 0;
width: 100%;
padding: 6rem 0;
background: var(--ifm-background-color);
}
.featureSvg {
height: 200px;
width: 200px;
.featuresHeader {
text-align: center;
margin-bottom: 4rem;
}
.featuresTitle {
font-size: 2.5rem;
font-weight: 800;
background: var(--debros-gradient-secondary);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 1rem;
}
.featuresSubtitle {
font-size: 1.2rem;
color: var(--ifm-color-content-secondary);
max-width: 600px;
margin: 0 auto;
line-height: 1.6;
}
.featuresGrid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 2rem;
margin-top: 2rem;
}
.featureCard {
display: flex;
flex-direction: column;
height: 100%;
padding: 2.5rem;
background: var(--ifm-background-surface-color);
border: 1px solid rgba(139, 92, 246, 0.1);
border-radius: 20px;
transition: all 0.4s ease;
position: relative;
overflow: hidden;
}
.featureCard::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: var(--debros-gradient-secondary);
opacity: 0;
transition: opacity 0.3s ease;
}
.featureCard:hover {
transform: translateY(-8px);
box-shadow: 0 20px 40px rgba(139, 92, 246, 0.15);
border-color: rgba(139, 92, 246, 0.3);
}
.featureCard:hover::before {
opacity: 1;
}
.featureCardHighlight {
background: linear-gradient(135deg, rgba(139, 92, 246, 0.05) 0%, rgba(59, 130, 246, 0.05) 100%);
border-color: rgba(139, 92, 246, 0.2);
}
.featureCardHighlight::before {
opacity: 0.7;
}
.featureIcon {
display: flex;
align-items: center;
justify-content: center;
width: 80px;
height: 80px;
margin: 0 auto 2rem;
background: rgba(139, 92, 246, 0.1);
border-radius: 20px;
border: 1px solid rgba(139, 92, 246, 0.2);
position: relative;
overflow: hidden;
}
.featureIcon::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: var(--debros-gradient-secondary);
opacity: 0;
transition: opacity 0.3s ease;
}
.featureCard:hover .featureIcon::before {
opacity: 0.1;
}
.iconEmoji {
font-size: 2.5rem;
position: relative;
z-index: 1;
}
.featureContent {
text-align: center;
}
.featureTitle {
font-size: 1.4rem;
font-weight: 700;
color: var(--ifm-color-content);
margin-bottom: 1rem;
line-height: 1.3;
}
.featureDescription {
font-size: 1rem;
color: var(--ifm-color-content-secondary);
line-height: 1.6;
margin: 0;
}
.featureDescription strong {
color: var(--ifm-color-primary);
font-weight: 600;
}
/* Responsive Design */
@media screen and (max-width: 996px) {
.features {
padding: 4rem 0;
}
.featuresTitle {
font-size: 2rem;
}
.featuresSubtitle {
font-size: 1.1rem;
}
.featuresGrid {
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1.5rem;
}
.featureCard {
padding: 2rem;
}
.featureIcon {
width: 70px;
height: 70px;
margin-bottom: 1.5rem;
}
.iconEmoji {
font-size: 2rem;
}
.featureTitle {
font-size: 1.2rem;
}
}
@media screen and (max-width: 576px) {
.featuresGrid {
grid-template-columns: 1fr;
}
.featureCard {
padding: 1.5rem;
}
.featuresTitle {
font-size: 1.8rem;
}
}

View File

@ -1,30 +1,260 @@
/**
* Any CSS included here will be global. The classic template
* bundles Infima by default. Infima is a CSS framework designed to
* work well for content-centric websites.
* DebrosFramework - Futuristic Dark Theme
* Custom styling for next-generation decentralized web framework
*/
/* You can override the default Infima variables here. */
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap');
/* Custom CSS Variables for DebrosFramework */
:root {
--ifm-color-primary: #2e8555;
--ifm-color-primary-dark: #29784c;
--ifm-color-primary-darker: #277148;
--ifm-color-primary-darkest: #205d3b;
--ifm-color-primary-light: #33925d;
--ifm-color-primary-lighter: #359962;
--ifm-color-primary-lightest: #3cad6e;
/* Primary colors - Cyber Purple/Blue gradient */
--ifm-color-primary: #7c3aed;
--ifm-color-primary-dark: #6d28d9;
--ifm-color-primary-darker: #5b21b6;
--ifm-color-primary-darkest: #4c1d95;
--ifm-color-primary-light: #8b5cf6;
--ifm-color-primary-lighter: #a78bfa;
--ifm-color-primary-lightest: #c4b5fd;
/* Accent colors */
--debros-accent-cyan: #06b6d4;
--debros-accent-emerald: #10b981;
--debros-accent-rose: #f43f5e;
--debros-accent-amber: #f59e0b;
/* Background gradients */
--debros-gradient-primary: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
--debros-gradient-secondary: linear-gradient(135deg, #7c3aed 0%, #3b82f6 50%, #06b6d4 100%);
--debros-gradient-hero: linear-gradient(135deg, #0f0f23 0%, #1a1a2e 50%, #16213e 100%);
/* Typography */
--ifm-font-family-base: 'Space Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--ifm-font-family-monospace: 'JetBrains Mono', SFMono-Regular, Menlo, Monaco, Consolas, monospace;
--ifm-code-font-size: 95%;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
/* Light theme overrides */
--ifm-background-color: #ffffff;
--ifm-background-surface-color: #f8fafc;
--docusaurus-highlighted-code-line-bg: rgba(124, 58, 237, 0.1);
}
/* For readability concerns, you should choose a lighter palette in dark mode. */
/* Dark theme - Default for DebrosFramework */
[data-theme='dark'] {
--ifm-color-primary: #25c2a0;
--ifm-color-primary-dark: #21af90;
--ifm-color-primary-darker: #1fa588;
--ifm-color-primary-darkest: #1a8870;
--ifm-color-primary-light: #29d5b0;
--ifm-color-primary-lighter: #32d8b4;
--ifm-color-primary-lightest: #4fddbf;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
/* Primary colors for dark theme */
--ifm-color-primary: #8b5cf6;
--ifm-color-primary-dark: #7c3aed;
--ifm-color-primary-darker: #6d28d9;
--ifm-color-primary-darkest: #5b21b6;
--ifm-color-primary-light: #a78bfa;
--ifm-color-primary-lighter: #c4b5fd;
--ifm-color-primary-lightest: #ddd6fe;
/* Dark background system */
--ifm-background-color: #0a0a0f;
--ifm-background-surface-color: #111827;
--ifm-color-content: #e5e7eb;
--ifm-color-content-secondary: #9ca3af;
/* Navbar dark styling */
--ifm-navbar-background-color: rgba(17, 24, 39, 0.95);
--ifm-navbar-shadow: 0 4px 28px rgba(0, 0, 0, 0.3);
/* Sidebar dark styling */
--ifm-menu-color: #d1d5db;
--ifm-menu-color-background-active: rgba(139, 92, 246, 0.1);
--ifm-menu-color-background-hover: rgba(139, 92, 246, 0.05);
/* Code highlighting */
--docusaurus-highlighted-code-line-bg: rgba(139, 92, 246, 0.2);
/* Footer dark styling */
--ifm-footer-background-color: #030712;
--ifm-footer-color: #9ca3af;
--ifm-footer-link-color: #d1d5db;
--ifm-footer-title-color: #f3f4f6;
}
/* Global Typography Enhancements */
body {
font-feature-settings: 'liga', 'kern';
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* Scrollbar Styling */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: var(--ifm-color-primary);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--ifm-color-primary-dark);
}
/* Navbar Enhancements */
.navbar {
backdrop-filter: blur(20px);
border-bottom: 1px solid rgba(139, 92, 246, 0.1);
transition: all 0.3s ease;
}
.navbar__title {
font-weight: 700;
font-size: 1.25rem;
background: var(--debros-gradient-secondary);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
.navbar__item {
font-weight: 500;
}
.navbar__link:hover {
color: var(--ifm-color-primary);
}
/* Button Enhancements */
.button {
font-weight: 600;
border-radius: 12px;
transition: all 0.3s ease;
font-family: var(--ifm-font-family-base);
}
.button--primary {
background: var(--debros-gradient-secondary);
border: none;
box-shadow: 0 4px 14px rgba(139, 92, 246, 0.3);
}
.button--primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(139, 92, 246, 0.4);
}
.button--secondary {
background: transparent;
border: 2px solid var(--ifm-color-primary);
color: var(--ifm-color-primary);
}
.button--secondary:hover {
background: var(--ifm-color-primary);
color: white;
transform: translateY(-2px);
}
/* Code Block Enhancements */
.prism-code {
border-radius: 12px;
border: 1px solid rgba(139, 92, 246, 0.2);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
}
.code {
background: rgba(139, 92, 246, 0.1);
border: 1px solid rgba(139, 92, 246, 0.2);
border-radius: 6px;
padding: 0.2em 0.4em;
font-weight: 500;
}
/* Table Enhancements */
.table {
border-radius: 12px;
overflow: hidden;
border: 1px solid rgba(139, 92, 246, 0.1);
}
.table thead tr {
background: rgba(139, 92, 246, 0.1);
}
/* Card Components */
.card {
background: var(--ifm-background-surface-color);
border: 1px solid rgba(139, 92, 246, 0.1);
border-radius: 16px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 32px rgba(139, 92, 246, 0.2);
}
/* Glow Effects */
.glow {
position: relative;
}
.glow::before {
content: '';
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
background: var(--debros-gradient-secondary);
border-radius: inherit;
opacity: 0;
transition: opacity 0.3s ease;
z-index: -1;
}
.glow:hover::before {
opacity: 0.7;
}
/* Responsive Design */
@media screen and (max-width: 996px) {
.navbar__title {
font-size: 1.1rem;
}
.button {
font-size: 0.9rem;
}
}
/* Animation Utilities */
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes pulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
.animate-fade-in-up {
animation: fadeInUp 0.6s ease-out;
}
.animate-pulse {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

View File

@ -1,23 +1,449 @@
/**
* CSS files with the .module.css suffix will be treated as CSS modules
* and scoped locally.
* DebrosFramework Landing Page Styles
* Futuristic design with cyber-aesthetic
*/
.heroBanner {
padding: 4rem 0;
/* Hero Section */
.hero {
position: relative;
min-height: 100vh;
display: flex;
align-items: center;
background: var(--debros-gradient-hero);
overflow: hidden;
}
.heroBackground {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 0;
}
.gridPattern {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image:
linear-gradient(rgba(139, 92, 246, 0.1) 1px, transparent 1px),
linear-gradient(90deg, rgba(139, 92, 246, 0.1) 1px, transparent 1px);
background-size: 50px 50px;
animation: gridMove 20s linear infinite;
}
@keyframes gridMove {
0% {
transform: translate(0, 0);
}
100% {
transform: translate(50px, 50px);
}
}
.glowOrb1,
.glowOrb2,
.glowOrb3 {
position: absolute;
border-radius: 50%;
filter: blur(60px);
animation: float 8s ease-in-out infinite;
}
.glowOrb1 {
width: 300px;
height: 300px;
background: radial-gradient(circle, rgba(124, 58, 237, 0.3) 0%, transparent 70%);
top: 10%;
left: 10%;
animation-delay: 0s;
}
.glowOrb2 {
width: 200px;
height: 200px;
background: radial-gradient(circle, rgba(59, 130, 246, 0.2) 0%, transparent 70%);
top: 60%;
right: 20%;
animation-delay: -3s;
}
.glowOrb3 {
width: 250px;
height: 250px;
background: radial-gradient(circle, rgba(6, 182, 212, 0.2) 0%, transparent 70%);
bottom: 20%;
left: 50%;
animation-delay: -6s;
}
@keyframes float {
0%, 100% {
transform: translateY(0px) rotate(0deg);
}
33% {
transform: translateY(-20px) rotate(120deg);
}
66% {
transform: translateY(10px) rotate(240deg);
}
}
.heroContent {
position: relative;
z-index: 2;
text-align: center;
max-width: 800px;
margin: 0 auto;
padding: 2rem;
}
.badge {
display: inline-block;
margin-bottom: 2rem;
animation: fadeInUp 0.6s ease-out;
}
.badgeText {
background: rgba(139, 92, 246, 0.1);
border: 1px solid rgba(139, 92, 246, 0.3);
color: var(--ifm-color-primary);
padding: 0.5rem 1rem;
border-radius: 50px;
font-size: 0.9rem;
font-weight: 600;
backdrop-filter: blur(10px);
}
.heroTitle {
font-size: 4rem;
font-weight: 800;
margin-bottom: 1.5rem;
line-height: 1.1;
animation: fadeInUp 0.6s ease-out 0.2s both;
}
.titleGradient {
background: var(--debros-gradient-secondary);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
display: inline-block;
}
.heroSubtitle {
font-size: 1.5rem;
font-weight: 600;
color: var(--ifm-color-primary);
margin-bottom: 1rem;
animation: fadeInUp 0.6s ease-out 0.4s both;
}
.heroDescription {
font-size: 1.1rem;
color: var(--ifm-color-content-secondary);
margin-bottom: 3rem;
line-height: 1.6;
animation: fadeInUp 0.6s ease-out 0.6s both;
}
.heroButtons {
display: flex;
gap: 1rem;
justify-content: center;
flex-wrap: wrap;
margin-bottom: 3rem;
animation: fadeInUp 0.6s ease-out 0.8s both;
}
.primaryButton {
position: relative;
overflow: hidden;
}
@media screen and (max-width: 996px) {
.heroBanner {
padding: 2rem;
}
.primaryButton::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
transition: left 0.5s;
}
.buttons {
.primaryButton:hover::before {
left: 100%;
}
.buttonIcon {
margin-left: 0.5rem;
transition: transform 0.3s ease;
}
.primaryButton:hover .buttonIcon {
transform: translateX(4px);
}
.secondaryButton {
backdrop-filter: blur(10px);
}
.quickStart {
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
flex-wrap: wrap;
animation: fadeInUp 0.6s ease-out 1s both;
}
.quickStartLabel {
font-size: 0.9rem;
color: var(--ifm-color-content-secondary);
font-weight: 500;
}
.codeSnippet {
background: rgba(139, 92, 246, 0.1);
border: 1px solid rgba(139, 92, 246, 0.3);
color: var(--ifm-color-primary);
padding: 0.5rem 1rem;
border-radius: 8px;
font-family: var(--ifm-font-family-monospace);
font-size: 0.9rem;
backdrop-filter: blur(10px);
}
/* Stats Section */
.stats {
padding: 4rem 0;
background: var(--ifm-background-surface-color);
border-top: 1px solid rgba(139, 92, 246, 0.1);
}
/* Video Section */
.videoSection {
padding: 6rem 0;
background: var(--ifm-background-color);
border-top: 1px solid rgba(139, 92, 246, 0.1);
}
.videoHeader {
text-align: center;
margin-bottom: 4rem;
}
.videoTitle {
font-size: 2.5rem;
font-weight: 800;
background: var(--debros-gradient-secondary);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 1rem;
}
.videoSubtitle {
font-size: 1.2rem;
color: var(--ifm-color-content-secondary);
max-width: 600px;
margin: 0 auto;
line-height: 1.6;
}
.videoContainer {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 3rem;
align-items: start;
}
.videoWrapper {
position: relative;
width: 100%;
height: 0;
padding-bottom: 56.25%; /* 16:9 aspect ratio */
background: var(--ifm-background-surface-color);
border-radius: 16px;
overflow: hidden;
border: 1px solid rgba(139, 92, 246, 0.2);
box-shadow: 0 8px 32px rgba(139, 92, 246, 0.1);
}
.videoEmbed {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: none;
}
.videoFeatures {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.videoFeature {
padding: 1.5rem;
background: var(--ifm-background-surface-color);
border: 1px solid rgba(139, 92, 246, 0.1);
border-radius: 12px;
font-size: 1rem;
line-height: 1.5;
transition: all 0.3s ease;
}
.videoFeature:hover {
transform: translateY(-2px);
box-shadow: 0 8px 24px rgba(139, 92, 246, 0.15);
border-color: rgba(139, 92, 246, 0.3);
}
.videoFeature strong {
color: var(--ifm-color-primary);
font-weight: 600;
}
.statsGrid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 2rem;
max-width: 800px;
margin: 0 auto;
}
.statItem {
text-align: center;
padding: 2rem 1rem;
background: var(--ifm-background-color);
border: 1px solid rgba(139, 92, 246, 0.1);
border-radius: 16px;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.statItem::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background: var(--debros-gradient-secondary);
}
.statItem:hover {
transform: translateY(-8px);
box-shadow: 0 16px 40px rgba(139, 92, 246, 0.2);
}
.statNumber {
font-size: 2.5rem;
font-weight: 800;
color: var(--ifm-color-primary);
margin-bottom: 0.5rem;
font-family: var(--ifm-font-family-base);
}
.statLabel {
font-size: 1rem;
font-weight: 600;
color: var(--ifm-color-content-secondary);
text-transform: uppercase;
letter-spacing: 0.5px;
}
/* Responsive Design */
@media screen and (max-width: 996px) {
.hero {
min-height: 80vh;
}
.heroTitle {
font-size: 2.5rem;
}
.heroSubtitle {
font-size: 1.2rem;
}
.heroDescription {
font-size: 1rem;
}
.heroButtons {
flex-direction: column;
align-items: center;
}
.quickStart {
flex-direction: column;
gap: 0.5rem;
}
.statsGrid {
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
}
.videoSection {
padding: 4rem 0;
}
.videoTitle {
font-size: 2rem;
}
.videoSubtitle {
font-size: 1.1rem;
}
.videoContainer {
grid-template-columns: 1fr;
gap: 2rem;
}
.glowOrb1,
.glowOrb2,
.glowOrb3 {
width: 150px;
height: 150px;
}
}
@media screen and (max-width: 576px) {
.heroTitle {
font-size: 2rem;
}
.statsGrid {
grid-template-columns: 1fr;
}
.statItem {
padding: 1.5rem 1rem;
}
.statNumber {
font-size: 2rem;
}
.videoTitle {
font-size: 1.8rem;
}
.videoFeatures {
gap: 1rem;
}
.videoFeature {
padding: 1rem;
}
}

View File

@ -8,24 +8,128 @@ import Heading from '@theme/Heading';
import styles from './index.module.css';
function HomepageHeader() {
function HeroSection() {
const {siteConfig} = useDocusaurusContext();
return (
<header className={clsx('hero hero--primary', styles.heroBanner)}>
<section className={styles.hero}>
<div className={styles.heroBackground}>
<div className={styles.gridPattern}></div>
<div className={styles.glowOrb1}></div>
<div className={styles.glowOrb2}></div>
<div className={styles.glowOrb3}></div>
</div>
<div className="container">
<Heading as="h1" className="hero__title">
{siteConfig.title}
</Heading>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<div className={styles.buttons}>
<Link
className="button button--secondary button--lg"
to="/docs/intro">
Docusaurus Tutorial - 5min
</Link>
<div className={styles.heroContent}>
<div className={styles.badge}>
<span className={styles.badgeText}>🚀 Beta Release</span>
</div>
<Heading as="h1" className={styles.heroTitle}>
<span className={styles.titleGradient}>Debros Network</span>
</Heading>
<p className={styles.heroSubtitle}>
{siteConfig.tagline}
</p>
<p className={styles.heroDescription}>
Build scalable, decentralized applications with ease using our next-generation
framework powered by OrbitDB, IPFS, and cutting-edge web technologies.
</p>
<div className={styles.heroButtons}>
<Link
className={clsx('button button--primary button--lg', styles.primaryButton)}
to="/docs/getting-started">
Get Started
<span className={styles.buttonIcon}></span>
</Link>
<Link
className={clsx('button button--secondary button--lg', styles.secondaryButton)}
to="/docs/intro">
View Documentation
</Link>
</div>
<div className={styles.quickStart}>
<span className={styles.quickStartLabel}>Quick Start:</span>
<code className={styles.codeSnippet}>
npm create debros-app my-app
</code>
</div>
</div>
</div>
</header>
</section>
);
}
function StatsSection() {
return (
<section className={styles.stats}>
<div className="container">
<div className={styles.statsGrid}>
<div className={styles.statItem}>
<div className={styles.statNumber}>100%</div>
<div className={styles.statLabel}>TypeScript</div>
</div>
<div className={styles.statItem}>
<div className={styles.statNumber}>Zero</div>
<div className={styles.statLabel}>Config</div>
</div>
<div className={styles.statItem}>
<div className={styles.statNumber}></div>
<div className={styles.statLabel}>Scalability</div>
</div>
<div className={styles.statItem}>
<div className={styles.statNumber}>🌐</div>
<div className={styles.statLabel}>Decentralized</div>
</div>
</div>
</div>
</section>
);
}
function VideoSection() {
return (
<section className={styles.videoSection}>
<div className="container">
<div className={styles.videoHeader}>
<Heading as="h2" className={styles.videoTitle}>
See Debros Network in Action
</Heading>
<p className={styles.videoSubtitle}>
Watch our comprehensive tutorial to learn how to build your first decentralized application
</p>
</div>
<div className={styles.videoContainer}>
<div className={styles.videoWrapper}>
{/* Replace VIDEO_ID_HERE with your actual YouTube video ID */}
<iframe
className={styles.videoEmbed}
src="https://www.youtube.com/embed/VIDEO_ID_HERE?rel=0&modestbranding=1&autohide=1&showinfo=0"
title="Debros Network Tutorial"
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
></iframe>
</div>
<div className={styles.videoFeatures}>
<div className={styles.videoFeature}>
🚀 <strong>Quick Start:</strong> Get up and running in under 5 minutes
</div>
<div className={styles.videoFeature}>
📚 <strong>Step-by-Step:</strong> Follow along with detailed explanations
</div>
<div className={styles.videoFeature}>
🔧 <strong>Best Practices:</strong> Learn the recommended patterns and approaches
</div>
</div>
</div>
</div>
</section>
);
}
@ -33,10 +137,12 @@ export default function Home(): ReactNode {
const {siteConfig} = useDocusaurusContext();
return (
<Layout
title={`Hello from ${siteConfig.title}`}
description="Description will go into a meta tag in <head />">
<HomepageHeader />
title={siteConfig.title}
description="Next-Generation Decentralized Web Framework - Build scalable, decentralized applications with ease using Debros Network">
<HeroSection />
<StatsSection />
<main>
<VideoSection />
<HomepageFeatures />
</main>
</Layout>

View File

@ -0,0 +1,19 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
roots: ['<rootDir>/tests/real-integration'],
testMatch: ['**/tests/**/*.test.ts'],
transform: {
'^.+\\.ts$': [
'ts-jest',
{
isolatedModules: true,
},
],
},
testTimeout: 120000, // 2 minutes for integration tests
verbose: true,
setupFilesAfterEnv: ['<rootDir>/tests/real-integration/blog-scenario/tests/setup.ts'],
maxWorkers: 1, // Run tests sequentially for integration tests
collectCoverage: false, // Skip coverage for integration tests
};

View File

@ -1,7 +1,7 @@
{
"name": "@debros/network",
"version": "0.5.0-beta",
"description": "Debros network core functionality for IPFS, libp2p and OrbitDB",
"version": "0.5.1-beta",
"description": "DebrosFramework - A powerful Node.js framework providing ORM-like abstraction over OrbitDB and IPFS for building scalable decentralized applications",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@ -20,16 +20,23 @@
"format": "prettier --write \"**/*.{ts,js,json,md}\"",
"lint:fix": "npx eslint src --fix",
"test:unit": "jest tests/unit",
"test:blog-integration": "tsx tests/real-integration/blog-scenario/scenarios/BlogTestRunner.ts",
"test:blog-integration": "jest --config=jest.integration.config.cjs tests/real-integration/blog-scenario/tests",
"test:real": "docker-compose -f tests/real-integration/blog-scenario/docker/docker-compose.blog.yml up --build --abort-on-container-exit"
},
"keywords": [
"ipfs",
"libp2p",
"orbitdb",
"debros",
"framework",
"orm",
"decentralized",
"ipfs",
"orbitdb",
"p2p",
"debros"
"typescript",
"models",
"query-builder",
"sharding",
"dapp",
"distributed"
],
"author": "Debros",
"license": "gnu-gpl-v3.0",
@ -69,6 +76,7 @@
]
},
"devDependencies": {
"axios": "^1.6.0",
"@eslint/js": "^9.24.0",
"@jest/globals": "^30.0.1",
"@orbitdb/core-types": "^1.0.14",

3
pnpm-lock.yaml generated
View File

@ -111,6 +111,9 @@ importers:
'@typescript-eslint/parser':
specifier: ^8.29.0
version: 8.29.0(eslint@9.24.0)(typescript@5.8.2)
axios:
specifier: ^1.6.0
version: 1.8.4(debug@4.4.0)
eslint:
specifier: ^9.24.0
version: 9.24.0

View File

@ -132,7 +132,7 @@ export class DebrosFramework {
this.status = {
initialized: false,
healthy: false,
version: '1.0.0', // This would come from package.json
version: '0.5.0-beta', // This would come from package.json
environment: this.config.environment || 'development',
services: {
orbitdb: 'disconnected',
@ -523,8 +523,7 @@ export class DebrosFramework {
// Overall health check - only require core services to be healthy
const coreServicesHealthy =
this.status.services.orbitdb === 'connected' &&
this.status.services.ipfs === 'connected';
this.status.services.orbitdb === 'connected' && this.status.services.ipfs === 'connected';
this.status.healthy = this.initialized && coreServicesHealthy;
} catch (error) {
@ -616,7 +615,7 @@ export class DebrosFramework {
return {
healthy: this.status.healthy,
services: { ...this.status.services },
lastCheck: this.status.lastHealthCheck
lastCheck: this.status.lastHealthCheck,
};
}

View File

@ -78,8 +78,8 @@ export type { FieldConfig, RelationshipConfig, ModelConfig, ValidationError } fr
// export { ValidationError } from './types/models'; // Already exported above
// Version information
export const FRAMEWORK_VERSION = '1.0.0';
export const API_VERSION = '1.0';
export const FRAMEWORK_VERSION = '0.5.0-beta';
export const API_VERSION = '0.5';
// Feature flags for conditional exports
export const FEATURES = {

View File

@ -29,7 +29,12 @@ export abstract class BaseModel {
// Then apply provided data, but only for properties that are explicitly provided
if (data && typeof data === 'object') {
Object.keys(data).forEach((key) => {
if (key !== '_loadedRelations' && key !== '_isDirty' && key !== '_isNew' && data[key] !== undefined) {
if (
key !== '_loadedRelations' &&
key !== '_isDirty' &&
key !== '_isNew' &&
data[key] !== undefined
) {
// Always set directly - the Field decorator's setter will handle validation and transformation
try {
(this as any)[key] = data[key];
@ -50,7 +55,6 @@ export abstract class BaseModel {
// Remove any instance properties that might shadow prototype getters
this.cleanupShadowingProperties();
}
private cleanupShadowingProperties(): void {
@ -75,13 +79,12 @@ export abstract class BaseModel {
this.markFieldAsModified(fieldName);
},
enumerable: true,
configurable: true
configurable: true,
});
}
}
}
// Core CRUD operations
async save(): Promise<this> {
if (this._isNew) {
@ -106,7 +109,6 @@ export abstract class BaseModel {
// Clean up any additional shadowing properties after setting timestamps
this.cleanupShadowingProperties();
// Validate after all field generation is complete
await this.validate();
@ -171,18 +173,29 @@ export abstract class BaseModel {
if (modelClass.scope === 'user') {
// For user-scoped models, we would need userId - for now, try global
const database = await framework.databaseManager?.getGlobalDatabase?.(modelClass.modelName || modelClass.name);
const database = await framework.databaseManager?.getGlobalDatabase?.(
modelClass.modelName || modelClass.name,
);
if (database && framework.databaseManager?.getDocument) {
data = await framework.databaseManager.getDocument(database, modelClass.storeType, id);
}
} else {
if (modelClass.sharding) {
const shard = framework.shardManager?.getShardForKey?.(modelClass.modelName || modelClass.name, id);
const shard = framework.shardManager?.getShardForKey?.(
modelClass.modelName || modelClass.name,
id,
);
if (shard && framework.databaseManager?.getDocument) {
data = await framework.databaseManager.getDocument(shard.database, modelClass.storeType, id);
data = await framework.databaseManager.getDocument(
shard.database,
modelClass.storeType,
id,
);
}
} else {
const database = await framework.databaseManager?.getGlobalDatabase?.(modelClass.modelName || modelClass.name);
const database = await framework.databaseManager?.getGlobalDatabase?.(
modelClass.modelName || modelClass.name,
);
if (database && framework.databaseManager?.getDocument) {
data = await framework.databaseManager.getDocument(database, modelClass.storeType, id);
}
@ -285,7 +298,7 @@ export abstract class BaseModel {
const query = new QueryBuilder<T>(this as any);
// Apply criteria as where clauses
Object.keys(criteria).forEach(key => {
Object.keys(criteria).forEach((key) => {
query.where(key, '=', criteria[key]);
});
@ -293,6 +306,12 @@ export abstract class BaseModel {
return results.length > 0 ? results[0] : null;
}
static async count<T extends BaseModel>(
this: typeof BaseModel & (new (data?: any) => T),
): Promise<number> {
return await new QueryBuilder<T>(this as any).count();
}
// Relationship operations
async load(relationships: string[]): Promise<this> {
const framework = this.getFrameworkInstance();
@ -385,6 +404,11 @@ export abstract class BaseModel {
// Include basic properties
result.id = this.id;
// For OrbitDB docstore compatibility, also include _id field
if (modelClass.storeType === 'docstore') {
result._id = this.id;
}
// Include loaded relations
this._loadedRelations.forEach((value, key) => {
result[key] = value;
@ -416,7 +440,6 @@ export abstract class BaseModel {
const errors: string[] = [];
const modelClass = this.constructor as typeof BaseModel;
// Validate each field using private keys (more reliable)
for (const [fieldName, fieldConfig] of modelClass.fields) {
const privateKey = `_${fieldName}`;
@ -435,7 +458,11 @@ export abstract class BaseModel {
return result;
}
private async validateField(fieldName: string, value: any, config: FieldConfig): Promise<string[]> {
private async validateField(
fieldName: string,
value: any,
config: FieldConfig,
): Promise<string[]> {
const errors: string[] = [];
// Required validation
@ -595,8 +622,21 @@ export abstract class BaseModel {
// Always ensure this field's getter works properly
this.ensureFieldGetter(fieldName);
// Try private key first
const privateKey = `_${fieldName}`;
return (this as any)[privateKey];
let value = (this as any)[privateKey];
// If private key is undefined, try the property getter as fallback
if (value === undefined) {
try {
value = (this as any)[fieldName];
} catch (error) {
console.warn(`Failed to access field ${fieldName} using getter:`, error);
// Ignore errors from getter
}
}
return value;
}
private ensureFieldGetter(fieldName: string): void {
@ -616,7 +656,7 @@ export abstract class BaseModel {
this.markFieldAsModified(fieldName);
},
enumerable: true,
configurable: true
configurable: true,
});
}
}
@ -676,7 +716,10 @@ export abstract class BaseModel {
try {
if (modelClass.scope === 'user') {
// For user-scoped models, we need a userId (check common field names)
const userId = (this as any).userId || (this as any).authorId || (this as any).ownerId;
const userId =
this.getFieldValue('userId') ||
this.getFieldValue('authorId') ||
this.getFieldValue('ownerId');
if (!userId) {
throw new Error('User-scoped models must have a userId, authorId, or ownerId field');
}
@ -705,7 +748,11 @@ export abstract class BaseModel {
} else {
// Use single global database
const database = await framework.databaseManager.getGlobalDatabase(modelClass.modelName);
await framework.databaseManager.addDocument(database, modelClass.storeType, this.toJSON());
await framework.databaseManager.addDocument(
database,
modelClass.storeType,
this.toJSON(),
);
}
}
} catch (error) {
@ -725,7 +772,10 @@ export abstract class BaseModel {
try {
if (modelClass.scope === 'user') {
const userId = (this as any).userId || (this as any).authorId || (this as any).ownerId;
const userId =
this.getFieldValue('userId') ||
this.getFieldValue('authorId') ||
this.getFieldValue('ownerId');
if (!userId) {
throw new Error('User-scoped models must have a userId, authorId, or ownerId field');
}
@ -779,7 +829,10 @@ export abstract class BaseModel {
try {
if (modelClass.scope === 'user') {
const userId = (this as any).userId || (this as any).authorId || (this as any).ownerId;
const userId =
this.getFieldValue('userId') ||
this.getFieldValue('authorId') ||
this.getFieldValue('ownerId');
if (!userId) {
throw new Error('User-scoped models must have a userId, authorId, or ownerId field');
}
@ -874,7 +927,7 @@ export abstract class BaseModel {
},
async all() {
return Array.from(this._data.values());
}
},
};
return {
@ -908,13 +961,13 @@ export abstract class BaseModel {
},
async getAllDocuments(_database: any, _type: string) {
return await mockDatabase.all();
}
},
},
shardManager: {
getShardForKey(_modelName: string, _key: string) {
return { database: mockDatabase };
}
}
},
},
};
}
return null;

View File

@ -7,18 +7,8 @@ export function Field(config: FieldConfig) {
validateFieldConfig(config);
// Handle ESM case where target might be undefined
if (!target) {
// In ESM environment, defer the decorator application
// Create a deferred setup that will be called when the class is actually used
console.warn(`Target is undefined for field:`, {
propertyKey,
propertyKeyType: typeof propertyKey,
propertyKeyValue: JSON.stringify(propertyKey),
configType: config.type,
target,
targetType: typeof target
});
deferredFieldSetup(config, propertyKey);
if (!target || typeof target !== 'object') {
// Skip the decorator if target is not available - the field will be handled later
return;
}

View File

@ -36,6 +36,15 @@ export class FrameworkOrbitDBService {
}
async openDatabase(name: string, type: StoreType): Promise<any> {
console.log('FrameworkOrbitDBService.openDatabase called with:', { name, type });
console.log('this.orbitDBService:', this.orbitDBService);
console.log('typeof this.orbitDBService.openDB:', typeof this.orbitDBService.openDB);
console.log('this.orbitDBService methods:', Object.getOwnPropertyNames(Object.getPrototypeOf(this.orbitDBService)));
if (typeof this.orbitDBService.openDB !== 'function') {
throw new Error(`openDB is not a function. Service type: ${typeof this.orbitDBService}, methods: ${Object.getOwnPropertyNames(Object.getPrototypeOf(this.orbitDBService))}`);
}
return await this.orbitDBService.openDB(name, type);
}

1646
system.txt

File diff suppressed because it is too large Load Diff

View File

@ -112,8 +112,8 @@ class BlogAPIServer {
const user = await User.create(sanitizedData);
console.log(`[${this.nodeId}] Created user: ${user.username} (${user.id})`);
res.status(201).json(user.toJSON());
console.log(`[${this.nodeId}] Created user: ${user.getFieldValue('username')} (${user.id})`);
res.status(201).json(user);
} catch (error) {
next(error);
}
@ -226,7 +226,7 @@ class BlogAPIServer {
const category = await Category.create(sanitizedData);
console.log(`[${this.nodeId}] Created category: ${category.name} (${category.id})`);
console.log(`[${this.nodeId}] Created category: ${category.getFieldValue('name')} (${category.id})`);
res.status(201).json(category);
} catch (error) {
next(error);
@ -276,7 +276,7 @@ class BlogAPIServer {
const post = await Post.create(sanitizedData);
console.log(`[${this.nodeId}] Created post: ${post.title} (${post.id})`);
console.log(`[${this.nodeId}] Created post: ${post.getFieldValue('title')} (${post.id})`);
res.status(201).json(post);
} catch (error) {
next(error);
@ -627,9 +627,6 @@ class BlogAPIServer {
const { OrbitDBService } = await import(
'../../../../src/framework/services/RealOrbitDBService'
);
const { FrameworkIPFSService, FrameworkOrbitDBService } = await import(
'../../../../src/framework/services/OrbitDBService'
);
// Initialize IPFS service
const ipfsService = new IPFSService({
@ -648,9 +645,9 @@ class BlogAPIServer {
await orbitDBService.init();
console.log(`[${this.nodeId}] OrbitDB service initialized`);
// Wrap services for framework
const frameworkIPFS = new FrameworkIPFSService(ipfsService);
const frameworkOrbitDB = new FrameworkOrbitDBService(orbitDBService);
// Debug: Check OrbitDB service methods
console.log(`[${this.nodeId}] OrbitDB service methods:`, Object.getOwnPropertyNames(Object.getPrototypeOf(orbitDBService)));
console.log(`[${this.nodeId}] Has openDB method:`, typeof orbitDBService.openDB === 'function');
// Initialize framework
this.framework = new DebrosFramework({
@ -669,8 +666,32 @@ class BlogAPIServer {
},
});
// Pass raw services to framework - it will wrap them itself
await this.framework.initialize(orbitDBService, ipfsService);
console.log(`[${this.nodeId}] DebrosFramework initialized successfully`);
// Register models with framework
this.framework.registerModel(User, {
scope: 'global',
type: 'docstore'
});
this.framework.registerModel(UserProfile, {
scope: 'global',
type: 'docstore'
});
this.framework.registerModel(Category, {
scope: 'global',
type: 'docstore'
});
this.framework.registerModel(Post, {
scope: 'user',
type: 'docstore'
});
this.framework.registerModel(Comment, {
scope: 'user',
type: 'docstore'
});
console.log(`[${this.nodeId}] Models registered with framework`);
}
}

View File

@ -2,6 +2,79 @@ import 'reflect-metadata';
import { BaseModel } from '../../../../src/framework/models/BaseModel';
import { Model, Field, HasMany, BelongsTo, HasOne, BeforeCreate, AfterCreate } from '../../../../src/framework/models/decorators';
// Force field registration by manually setting up field configurations
function setupFieldConfigurations() {
// User Profile fields
if (!UserProfile.fields) {
(UserProfile as any).fields = new Map();
}
UserProfile.fields.set('userId', { type: 'string', required: true });
UserProfile.fields.set('bio', { type: 'string', required: false });
UserProfile.fields.set('location', { type: 'string', required: false });
UserProfile.fields.set('website', { type: 'string', required: false });
UserProfile.fields.set('socialLinks', { type: 'object', required: false });
UserProfile.fields.set('interests', { type: 'array', required: false, default: [] });
UserProfile.fields.set('createdAt', { type: 'number', required: false, default: () => Date.now() });
UserProfile.fields.set('updatedAt', { type: 'number', required: false, default: () => Date.now() });
// User fields
if (!User.fields) {
(User as any).fields = new Map();
}
User.fields.set('username', { type: 'string', required: true, unique: true });
User.fields.set('email', { type: 'string', required: true, unique: true });
User.fields.set('displayName', { type: 'string', required: false });
User.fields.set('avatar', { type: 'string', required: false });
User.fields.set('isActive', { type: 'boolean', required: false, default: true });
User.fields.set('roles', { type: 'array', required: false, default: [] });
User.fields.set('createdAt', { type: 'number', required: false });
User.fields.set('lastLoginAt', { type: 'number', required: false });
// Category fields
if (!Category.fields) {
(Category as any).fields = new Map();
}
Category.fields.set('name', { type: 'string', required: true, unique: true });
Category.fields.set('slug', { type: 'string', required: true, unique: true });
Category.fields.set('description', { type: 'string', required: false });
Category.fields.set('color', { type: 'string', required: false });
Category.fields.set('isActive', { type: 'boolean', required: false, default: true });
Category.fields.set('createdAt', { type: 'number', required: false, default: () => Date.now() });
// Post fields
if (!Post.fields) {
(Post as any).fields = new Map();
}
Post.fields.set('title', { type: 'string', required: true });
Post.fields.set('slug', { type: 'string', required: true, unique: true });
Post.fields.set('content', { type: 'string', required: true });
Post.fields.set('excerpt', { type: 'string', required: false });
Post.fields.set('authorId', { type: 'string', required: true });
Post.fields.set('categoryId', { type: 'string', required: false });
Post.fields.set('tags', { type: 'array', required: false, default: [] });
Post.fields.set('status', { type: 'string', required: false, default: 'draft' });
Post.fields.set('featuredImage', { type: 'string', required: false });
Post.fields.set('isFeatured', { type: 'boolean', required: false, default: false });
Post.fields.set('viewCount', { type: 'number', required: false, default: 0 });
Post.fields.set('likeCount', { type: 'number', required: false, default: 0 });
Post.fields.set('createdAt', { type: 'number', required: false });
Post.fields.set('updatedAt', { type: 'number', required: false });
Post.fields.set('publishedAt', { type: 'number', required: false });
// Comment fields
if (!Comment.fields) {
(Comment as any).fields = new Map();
}
Comment.fields.set('content', { type: 'string', required: true });
Comment.fields.set('postId', { type: 'string', required: true });
Comment.fields.set('authorId', { type: 'string', required: true });
Comment.fields.set('parentId', { type: 'string', required: false });
Comment.fields.set('isApproved', { type: 'boolean', required: false, default: true });
Comment.fields.set('likeCount', { type: 'number', required: false, default: 0 });
Comment.fields.set('createdAt', { type: 'number', required: false });
Comment.fields.set('updatedAt', { type: 'number', required: false });
}
// User Profile Model
@Model({
scope: 'global',
@ -369,3 +442,6 @@ export interface UpdatePostRequest {
featuredImage?: string;
isFeatured?: boolean;
}
// Initialize field configurations after all models are defined
setupFieldConfigurations();