This repository has been archived on 2025-08-03. You can view files and clone it, but cannot push or open issues or pull requests.
network-orbit/.claude/development-guidelines.md

10 KiB

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

// 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

// 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

// 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

// 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
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

// 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

// 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

/**
 * 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

@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

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

// 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

// 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

// 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

// 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.