/** * Complete DebrosFramework Example * * This example demonstrates the complete DebrosFramework in action, * showcasing all major features and capabilities in a real-world scenario: * - Framework initialization with all components * - Model definition with decorators and relationships * - Database operations and querying * - Automatic features (pinning, PubSub, caching) * - Migration system for schema evolution * - Performance monitoring and optimization * - Error handling and recovery */ import { DebrosFramework, BaseModel, Model, Field, BelongsTo, HasMany, BeforeCreate, AfterCreate, createMigration, DEVELOPMENT_CONFIG, PRODUCTION_CONFIG } from '../src/framework'; // Define comprehensive models for a decentralized social platform @Model({ scope: 'global', type: 'docstore', pinning: { strategy: 'fixed', factor: 3 }, sharding: { strategy: 'hash', count: 8, 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; @Field({ type: 'string', required: false }) bio?: string; @Field({ type: 'string', required: false }) profilePicture?: string; @Field({ type: 'boolean', default: false }) isVerified!: boolean; @Field({ type: 'number', default: 0 }) followerCount!: number; @Field({ type: 'number', default: 0 }) followingCount!: number; @Field({ type: 'object', default: {} }) settings!: any; @HasMany(Post, 'userId') posts!: Post[]; @HasMany(Follow, 'followerId') following!: Follow[]; @BeforeCreate() async validateUser() { if (this.username.length < 3) { throw new Error('Username must be at least 3 characters long'); } if (!this.email.includes('@')) { throw new Error('Invalid email format'); } } @AfterCreate() async setupUserDefaults() { this.settings = { theme: 'light', notifications: true, privacy: 'public', createdAt: Date.now() }; } // Custom methods async updateProfile(updates: { bio?: string; profilePicture?: string }): Promise { Object.assign(this, updates); await this.save(); } async getPopularPosts(limit: number = 10): Promise { return await Post .whereUser(this.id) .where('isPublic', '=', true) .orderBy('likeCount', 'desc') .limit(limit) .exec(); } } @Model({ scope: 'user', type: 'docstore', pinning: { strategy: 'popularity', factor: 1.5 } }) 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; @Field({ type: 'boolean', default: true }) isPublic!: boolean; @Field({ type: 'array', default: [] }) tags!: string[]; @Field({ type: 'number', default: 0 }) likeCount!: number; @Field({ type: 'number', default: 0 }) commentCount!: number; @Field({ type: 'string', default: 'text' }) contentType!: string; @Field({ type: 'object', default: {} }) metadata!: any; @BelongsTo(User, 'userId') author!: User; @HasMany(Comment, 'postId') comments!: Comment[]; @BeforeCreate() async processContent() { // Auto-detect content type and extract metadata this.metadata = { wordCount: this.content.split(' ').length, hasLinks: /https?:\/\//.test(this.content), hashtags: this.extractHashtags(), readTime: Math.ceil(this.content.split(' ').length / 200) // Reading speed }; if (this.metadata.hasLinks) { this.contentType = 'rich'; } } private extractHashtags(): string[] { const hashtags = this.content.match(/#\w+/g) || []; return hashtags.map(tag => tag.slice(1).toLowerCase()); } async toggleLike(): Promise { this.likeCount += 1; await this.save(); } async addComment(userId: string, content: string): Promise { const comment = await Comment.create({ content, userId, postId: this.id }); this.commentCount += 1; await this.save(); return comment; } } @Model({ scope: 'user', type: 'docstore' }) export class Comment extends BaseModel { @Field({ type: 'string', required: true }) content!: string; @Field({ type: 'string', required: true }) userId!: string; @Field({ type: 'string', required: true }) postId!: string; @Field({ type: 'string', required: false }) parentId?: string; @Field({ type: 'number', default: 0 }) likeCount!: number; @Field({ type: 'number', default: 0 }) threadDepth!: number; @BelongsTo(User, 'userId') author!: User; @BelongsTo(Post, 'postId') post!: Post; @BelongsTo(Comment, 'parentId') parent?: Comment; @HasMany(Comment, 'parentId') replies!: Comment[]; } @Model({ scope: 'global', type: 'keyvalue' }) export class Follow extends BaseModel { @Field({ type: 'string', required: true }) followerId!: string; @Field({ type: 'string', required: true }) followingId!: string; @Field({ type: 'boolean', default: false }) isMutual!: boolean; @Field({ type: 'string', default: 'general' }) category!: string; @BelongsTo(User, 'followerId') follower!: User; @BelongsTo(User, 'followingId') following!: User; } export class CompleteFrameworkExample { private framework: DebrosFramework; private sampleUsers: User[] = []; private samplePosts: Post[] = []; constructor() { // Initialize framework with comprehensive configuration this.framework = new DebrosFramework({ ...DEVELOPMENT_CONFIG, features: { autoMigration: true, automaticPinning: true, pubsub: true, queryCache: true, relationshipCache: true }, performance: { queryTimeout: 30000, migrationTimeout: 300000, maxConcurrentOperations: 200, batchSize: 100 }, monitoring: { enableMetrics: true, logLevel: 'info', metricsInterval: 30000 } }); } async runCompleteExample(): Promise { console.log('๐ŸŽฏ Running Complete DebrosFramework Example'); console.log('==========================================\n'); try { await this.initializeFramework(); await this.setupModelsAndMigrations(); await this.demonstrateModelOperations(); await this.demonstrateQuerySystem(); await this.demonstrateRelationships(); await this.demonstrateAutomaticFeatures(); await this.demonstratePerformanceOptimization(); await this.demonstrateErrorHandling(); await this.showFrameworkStatistics(); console.log('โœ… Complete framework example finished successfully!\n'); } catch (error) { console.error('โŒ Framework example failed:', error); throw error; } finally { await this.cleanup(); } } async initializeFramework(): Promise { console.log('๐Ÿš€ Initializing DebrosFramework'); console.log('===============================\n'); // In a real application, you would pass actual OrbitDB and IPFS instances const mockOrbitDB = this.createMockOrbitDB(); const mockIPFS = this.createMockIPFS(); await this.framework.initialize(mockOrbitDB, mockIPFS); // Register models this.framework.registerModel(User); this.framework.registerModel(Post); this.framework.registerModel(Comment); this.framework.registerModel(Follow); console.log('Framework initialization completed'); console.log(`Status: ${this.framework.getStatus().healthy ? 'Healthy' : 'Unhealthy'}`); console.log(`Environment: ${this.framework.getStatus().environment}`); console.log(''); } async setupModelsAndMigrations(): Promise { console.log('๐Ÿ”„ Setting Up Models and Migrations'); console.log('===================================\n'); // Create sample migrations const addProfileEnhancements = createMigration( 'add_profile_enhancements', '1.1.0', 'Add profile enhancements to User model' ) .description('Add profile picture and verification status to users') .addField('User', 'profilePicture', { type: 'string', required: false }) .addField('User', 'isVerified', { type: 'boolean', default: false }) .build(); const addPostMetadata = createMigration( 'add_post_metadata', '1.2.0', 'Add metadata to Post model' ) .description('Add content metadata and engagement metrics') .addField('Post', 'contentType', { type: 'string', default: 'text' }) .addField('Post', 'metadata', { type: 'object', default: {} }) .transformData('Post', (post) => { return { ...post, metadata: { wordCount: post.content ? post.content.split(' ').length : 0, transformedAt: Date.now() } }; }) .build(); // Register migrations await this.framework.registerMigration(addProfileEnhancements); await this.framework.registerMigration(addPostMetadata); // Run pending migrations const pendingMigrations = this.framework.getPendingMigrations(); console.log(`Found ${pendingMigrations.length} pending migrations`); if (pendingMigrations.length > 0) { const migrationManager = this.framework.getMigrationManager(); if (migrationManager) { const results = await migrationManager.runPendingMigrations({ dryRun: false, stopOnError: true }); console.log(`Completed ${results.filter(r => r.success).length} migrations`); } } console.log(''); } async demonstrateModelOperations(): Promise { console.log('๐Ÿ‘ฅ Demonstrating Model Operations'); console.log('=================================\n'); // Create users with validation and hooks console.log('Creating users...'); for (let i = 0; i < 5; i++) { const user = await User.create({ username: `frameuser${i}`, email: `frameuser${i}@example.com`, bio: `Framework test user ${i} with comprehensive features`, isVerified: i < 2 // First two users are verified }); this.sampleUsers.push(user); console.log(`โœ… Created user: ${user.username} (verified: ${user.isVerified})`); } // Create posts with automatic content processing console.log('\nCreating posts...'); for (let i = 0; i < 10; i++) { const user = this.sampleUsers[i % this.sampleUsers.length]; const post = await Post.create({ title: `Framework Demo Post ${i + 1}`, content: `This is a comprehensive demo post ${i + 1} showcasing the DebrosFramework capabilities. #framework #demo #orbitdb ${i % 3 === 0 ? 'https://example.com' : ''}`, userId: user.id, isPublic: true, tags: ['framework', 'demo', 'test'] }); this.samplePosts.push(post); console.log(`โœ… Created post: "${post.title}" by ${user.username}`); console.log(` Content type: ${post.contentType}, Word count: ${post.metadata.wordCount}`); } // Create comments and follows console.log('\nCreating interactions...'); let commentCount = 0; let followCount = 0; for (let i = 0; i < 15; i++) { const user = this.sampleUsers[Math.floor(Math.random() * this.sampleUsers.length)]; const post = this.samplePosts[Math.floor(Math.random() * this.samplePosts.length)]; await Comment.create({ content: `This is comment ${i + 1} on the framework demo post. Great work!`, userId: user.id, postId: post.id }); commentCount++; } // Create follow relationships for (let i = 0; i < this.sampleUsers.length; i++) { for (let j = 0; j < this.sampleUsers.length; j++) { if (i !== j && Math.random() > 0.6) { await Follow.create({ followerId: this.sampleUsers[i].id, followingId: this.sampleUsers[j].id, category: 'general' }); followCount++; } } } console.log(`โœ… Created ${commentCount} comments and ${followCount} follow relationships`); console.log(''); } async demonstrateQuerySystem(): Promise { console.log('๐Ÿ” Demonstrating Advanced Query System'); console.log('======================================\n'); // Complex queries with caching console.log('1. Complex filtering and sorting:'); const popularPosts = await Post .where('isPublic', '=', true) .where('likeCount', '>', 0) .orderBy('likeCount', 'desc') .orderBy('createdAt', 'desc') .limit(5) .exec(); console.log(`Found ${popularPosts.length} popular posts`); // User-scoped queries console.log('\n2. User-scoped queries:'); const userPosts = await Post .whereUser(this.sampleUsers[0].id) .where('isPublic', '=', true) .exec(); console.log(`User ${this.sampleUsers[0].username} has ${userPosts.length} public posts`); // Aggregation queries console.log('\n3. Aggregation queries:'); const totalPosts = await Post.count(); const totalPublicPosts = await Post.where('isPublic', '=', true).count(); const averageLikes = await Post.avg('likeCount'); console.log(`Total posts: ${totalPosts}`); console.log(`Public posts: ${totalPublicPosts}`); console.log(`Average likes: ${averageLikes.toFixed(2)}`); // Query with relationships console.log('\n4. Queries with relationships:'); const postsWithAuthors = await Post .where('isPublic', '=', true) .with(['author']) .limit(3) .exec(); console.log('Posts with preloaded authors:'); postsWithAuthors.forEach(post => { const author = post.getRelation('author'); console.log(`- "${post.title}" by ${author ? author.username : 'Unknown'}`); }); console.log(''); } async demonstrateRelationships(): Promise { console.log('๐Ÿ”— Demonstrating Relationship System'); console.log('====================================\n'); const user = this.sampleUsers[0]; const post = this.samplePosts[0]; // Lazy loading console.log('1. Lazy loading relationships:'); console.log(`Loading posts for user: ${user.username}`); const userPosts = await user.loadRelation('posts'); console.log(`Loaded ${Array.isArray(userPosts) ? userPosts.length : 0} posts`); console.log(`\nLoading comments for post: "${post.title}"`); const comments = await post.loadRelation('comments'); console.log(`Loaded ${Array.isArray(comments) ? comments.length : 0} comments`); // Eager loading console.log('\n2. Eager loading for multiple items:'); const relationshipManager = this.framework.getRelationshipManager(); if (relationshipManager) { await relationshipManager.eagerLoadRelationships( this.samplePosts.slice(0, 3), ['author', 'comments'] ); console.log('Eager loaded author and comments for 3 posts:'); this.samplePosts.slice(0, 3).forEach((post, index) => { const author = post.getRelation('author'); const comments = post.getRelation('comments') || []; console.log(`${index + 1}. "${post.title}" by ${author ? author.username : 'Unknown'} (${comments.length} comments)`); }); } // Relationship constraints console.log('\n3. Constrained relationship loading:'); const recentComments = await post.loadRelationWithConstraints('comments', (query) => query.where('createdAt', '>', Date.now() - 86400000) // Last 24 hours .orderBy('createdAt', 'desc') .limit(3) ); console.log(`Loaded ${Array.isArray(recentComments) ? recentComments.length : 0} recent comments`); console.log(''); } async demonstrateAutomaticFeatures(): Promise { console.log('๐Ÿค– Demonstrating Automatic Features'); console.log('===================================\n'); // Pinning system console.log('1. Automatic pinning system:'); const pinningManager = this.framework.getPinningManager(); if (pinningManager) { // Setup pinning rules pinningManager.setPinningRule('Post', { strategy: 'popularity', factor: 1.5, maxPins: 50 }); pinningManager.setPinningRule('User', { strategy: 'fixed', factor: 2.0, maxPins: 20 }); // Simulate content pinning for (let i = 0; i < 5; i++) { const post = this.samplePosts[i]; const hash = `content-hash-${post.id}`; // Simulate access await pinningManager.recordAccess(hash); await pinningManager.recordAccess(hash); const pinned = await pinningManager.pinContent(hash, 'Post', post.id, { title: post.title, likeCount: post.likeCount }); console.log(`Post "${post.title}": ${pinned ? 'PINNED' : 'NOT PINNED'}`); } const pinningStats = pinningManager.getStats(); console.log(`Pinning stats: ${pinningStats.totalPinned} items pinned`); } // PubSub system console.log('\n2. PubSub event system:'); const pubsubManager = this.framework.getPubSubManager(); if (pubsubManager) { let eventCount = 0; // Subscribe to model events await pubsubManager.subscribe('model.*', (event) => { eventCount++; console.log(`๐Ÿ“ก Event: ${event.type} for ${event.data?.modelName || 'unknown'}`); }); // Simulate model events await pubsubManager.publish('model.created', { modelName: 'Post', modelId: 'demo-post-1', userId: 'demo-user-1' }); await pubsubManager.publish('model.updated', { modelName: 'User', modelId: 'demo-user-1', changes: { bio: 'Updated bio' } }); // Wait for event processing await new Promise(resolve => setTimeout(resolve, 1000)); console.log(`Processed ${eventCount} events`); const pubsubStats = pubsubManager.getStats(); console.log(`PubSub stats: ${pubsubStats.totalPublished} published, ${pubsubStats.totalReceived} received`); } console.log(''); } async demonstratePerformanceOptimization(): Promise { console.log('๐Ÿš€ Demonstrating Performance Features'); console.log('=====================================\n'); // Cache warming console.log('1. Cache warming and optimization:'); await this.framework.warmupCaches(); // Query performance comparison console.log('\n2. Query performance comparison:'); const startTime = Date.now(); // First query (cold cache) await Post.where('isPublic', '=', true).limit(5).exec(); const coldTime = Date.now() - startTime; const warmStartTime = Date.now(); // Second query (warm cache) await Post.where('isPublic', '=', true).limit(5).exec(); const warmTime = Date.now() - warmStartTime; console.log(`Cold cache query: ${coldTime}ms`); console.log(`Warm cache query: ${warmTime}ms`); console.log(`Performance improvement: ${coldTime > 0 ? (coldTime / Math.max(warmTime, 1)).toFixed(2) : 'N/A'}x`); // Relationship loading optimization console.log('\n3. Relationship loading optimization:'); const relationshipManager = this.framework.getRelationshipManager(); if (relationshipManager) { const stats = relationshipManager.getRelationshipCacheStats(); console.log(`Relationship cache: ${stats.cache.totalEntries} entries`); console.log(`Cache hit rate: ${(stats.cache.hitRate * 100).toFixed(2)}%`); } console.log(''); } async demonstrateErrorHandling(): Promise { console.log('โš ๏ธ Demonstrating Error Handling'); console.log('=================================\n'); // Validation errors console.log('1. Model validation errors:'); try { await User.create({ username: 'x', // Too short email: 'invalid-email' // Invalid format }); } catch (error: any) { console.log(`โœ… Caught validation error: ${error.message}`); } // Query errors console.log('\n2. Query timeout handling:'); try { // Simulate slow query const result = await Post.where('nonExistentField', '=', 'value').exec(); console.log(`Query result: ${result.length} items`); } catch (error: any) { console.log(`โœ… Handled query error gracefully: ${error.message}`); } // Migration rollback console.log('\n3. Migration error recovery:'); const migrationManager = this.framework.getMigrationManager(); if (migrationManager) { try { const riskyMigration = createMigration( 'risky_migration', '99.0.0', 'Intentionally failing migration' ) .customOperation('Post', async () => { throw new Error('Simulated migration failure'); }) .build(); await migrationManager.registerMigration(riskyMigration); await migrationManager.runMigration(riskyMigration.id); } catch (error: any) { console.log(`โœ… Migration failed as expected and rolled back: ${error.message}`); } } console.log(''); } async showFrameworkStatistics(): Promise { console.log('๐Ÿ“Š Framework Statistics'); console.log('=======================\n'); const status = this.framework.getStatus(); const metrics = this.framework.getMetrics(); console.log('Status:'); console.log(`- Initialized: ${status.initialized}`); console.log(`- Healthy: ${status.healthy}`); console.log(`- Version: ${status.version}`); console.log(`- Environment: ${status.environment}`); console.log(`- Services: ${Object.entries(status.services).map(([name, status]) => `${name}:${status}`).join(', ')}`); console.log('\nMetrics:'); console.log(`- Uptime: ${(metrics.uptime / 1000).toFixed(2)} seconds`); console.log(`- Total models: ${metrics.totalModels}`); console.log(`- Queries executed: ${metrics.queriesExecuted}`); console.log(`- Migrations run: ${metrics.migrationsRun}`); console.log(`- Cache hit rate: ${(metrics.cacheHitRate * 100).toFixed(2)}%`); console.log(`- Average query time: ${metrics.averageQueryTime.toFixed(2)}ms`); console.log('\nMemory Usage:'); console.log(`- Query cache: ${(metrics.memoryUsage.queryCache / 1024).toFixed(2)} KB`); console.log(`- Relationship cache: ${(metrics.memoryUsage.relationshipCache / 1024).toFixed(2)} KB`); console.log(`- Total: ${(metrics.memoryUsage.total / 1024).toFixed(2)} KB`); console.log(''); } async cleanup(): Promise { console.log('๐Ÿงน Cleaning up framework...'); await this.framework.stop(); console.log('โœ… Framework stopped and cleaned up'); } // Mock service creation (in real usage, these would be actual services) private createMockOrbitDB(): any { return { create: async () => ({ add: async () => {}, get: async () => [], all: async () => [] }), open: async () => ({ add: async () => {}, get: async () => [], all: async () => [] }), disconnect: async () => {}, stores: {} }; } private createMockIPFS(): any { return { add: async () => ({ cid: 'mock-cid' }), cat: async () => Buffer.from('mock data'), pin: { add: async () => {}, rm: async () => {} }, pubsub: { subscribe: async () => {}, unsubscribe: async () => {}, publish: async () => {} }, object: { stat: async () => ({ CumulativeSize: 1024 }) } }; } } // Usage function export async function runCompleteFrameworkExample(): Promise { const example = new CompleteFrameworkExample(); await example.runCompleteExample(); } // Run if called directly if (require.main === module) { runCompleteFrameworkExample().catch(console.error); }