Email Repository Development Standards
This skill provides comprehensive development guidance for working with the Email Node.js repository, which implements an email client following SOLID principles and clean architecture patterns.
Build, Run, and Test Commands
When working with this repository, use the following commands:
1. **Install dependencies**: Run `npm install` to install all required packages
2. **Start the application**: Run `npm start` to launch the email client
3. **Run all tests**: Run `npm test` to execute the full test suite
4. **Run a specific test**: Run `npm test -- -t "test name"` to run a single test case
5. **Lint the codebase**: Run `npm run lint` to check code quality and style
Code Style Guidelines
Follow these conventions when writing or modifying code:
Formatting
Use 2-space indentation (not tabs)Remove all trailing whitespaceAlways use semicolons at the end of statementsImport Organization
Group imports by type: 1. Node.js built-in modules first
2. External npm packages second
3. Local modules last
Separate import groups with a blank lineNaming Conventions
**Variables and functions**: Use camelCase (e.g., `getUserEmail`, `messageCount`)**Classes and components**: Use PascalCase (e.g., `EmailService`, `ImapClient`)TypeScript Usage
Always use explicit types for function parametersAlways specify return types for functionsAvoid using `any` type unless absolutely necessaryPrefer interfaces over type aliases for object shapesError Handling
Wrap all async operations in try/catch blocksProvide informative, user-friendly error messagesLog errors with sufficient context for debuggingDon't expose sensitive information in error messagesDocumentation
Add JSDoc comments for all public functions and componentsDocument parameter types, return types, and purposeInclude usage examples in JSDoc for complex functionsDocument any non-obvious business logic or algorithmsCode Organization
Split code into modular components with single responsibilitiesKeep files focused and under 300 lines when possibleExtract reusable logic into utility functionsAvoid deep nesting (max 3-4 levels)Project Structure
This Node.js application follows clean architecture and SOLID principles. Understand these key directories:
**`src/application/useCases`**: Contains business logic and use cases. This is where the core application functionality lives, independent of infrastructure details.**`src/domain/interfaces`**: Defines contracts and interfaces. These abstractions allow for dependency inversion and loose coupling between layers.**`src/infrastructure/imap`**: Houses the IMAP implementation using the imapflow library. Email provider-specific details are isolated here.**`src/presentation/cli`**: Terminal user interface implementation using enquirer for interactive prompts.**`src/shared`**: Configuration files and dependency injection setup. Contains the tsyringe container configuration.Architecture Guidelines
When adding features or modifying code, adhere to these architectural principles:
SOLID Principles
**Single Responsibility**: Each class should have one reason to change**Open/Closed**: Open for extension, closed for modification**Liskov Substitution**: Subtypes must be substitutable for their base types**Interface Segregation**: Many specific interfaces are better than one general interface**Dependency Inversion**: Depend on abstractions, not concretionsDependency Injection
Use tsyringe for all dependency injectionRegister dependencies in the shared configuration layerInject dependencies through constructorsAvoid using the service locator patternLayered Architecture
Keep email provider implementation details isolated in the infrastructure layerBusiness logic in use cases should not depend on infrastructureUse interfaces to define contracts between layersThe domain layer should have no external dependenciesTesting Strategy
Write unit tests using Jest for all use casesMock dependencies using Jest's mocking capabilitiesTest behavior, not implementation detailsAim for high test coverage on business logicUse integration tests sparingly for critical pathsExamples
Good Import Organization
```typescript
// Node built-ins
import { readFile } from 'fs/promises';
import { join } from 'path';
// External packages
import { injectable, inject } from 'tsyringe';
import { ImapFlow } from 'imapflow';
// Local modules
import { IEmailRepository } from '../domain/interfaces/IEmailRepository';
import { EmailMessage } from '../domain/entities/EmailMessage';
```
Good Function Documentation
```typescript
/**
* Fetches unread emails from the user's inbox
* @param folderName - The name of the folder to search (default: 'INBOX')
* @param limit - Maximum number of emails to retrieve (default: 50)
* @returns Promise resolving to an array of EmailMessage objects
* @throws {ImapConnectionError} If connection to email server fails
*/
async function fetchUnreadEmails(
folderName: string = 'INBOX',
limit: number = 50
): Promise<EmailMessage[]> {
// Implementation
}
```
Good Dependency Injection Usage
```typescript
@injectable()
export class GetUnreadEmailsUseCase {
constructor(
@inject('IEmailRepository') private emailRepository: IEmailRepository
) {}
async execute(folderName: string): Promise<EmailMessage[]> {
return await this.emailRepository.getUnreadEmails(folderName);
}
}
```
Constraints and Important Notes
Never commit sensitive credentials or API keysAlways test changes with both unit and integration tests before committingMaintain backward compatibility when modifying public interfacesDocument breaking changes in commit messagesFollow the existing code style even if it differs from your preferencesPerformance: Be mindful of memory usage when handling large email attachmentsSecurity: Sanitize all user inputs before processingIMAP connections should be properly closed in finally blocks to prevent resource leaks