This document outlines the code organization principles and patterns used in the project.
- Each module has a single responsibility
- Clear boundaries between layers
- Minimal dependencies between modules
- Clean and maintainable code
- Strong typing throughout
- Interface-driven development
- Runtime type checking
- Proper error handling
- Self-contained modules
- Clear module interfaces
- Dependency injection
- Testable components
// Controller example
export class DataController {
constructor(private dataService: DataService) {}
async store(req: Request, res: Response) {
const data = await this.dataService.store(req.body);
res.json(data);
}
}// Service example
export class DataService {
constructor(private repository: Repository<Data>) {}
async store(data: DataInput): Promise<Data> {
// Business logic
return await this.repository.save(data);
}
}// Model example
@Entity()
export class Data {
@PrimaryColumn()
id: string;
@Column()
type: DataType;
@Column('json')
metadata: DataMetadata;
}// Interfaces
interface IDataService {
store(data: DataInput): Promise<Data>;
}
// Classes
class DataService implements IDataService {
// Implementation
}
// Enums
enum DataType {
DOCUMENT = 'DOCUMENT',
IMAGE = 'IMAGE'
}// Custom error classes
export class AppError extends Error {
constructor(
public statusCode: number,
message: string
) {
super(message);
}
}
// Error handling
try {
await service.process();
} catch (error) {
throw new AppError(500, error.message);
}// Proper async/await usage
async function processData() {
try {
const data = await fetchData();
return await processResult(data);
} catch (error) {
handleError(error);
}
}describe('DataService', () => {
it('should store data', async () => {
const result = await service.store(mockData);
expect(result).toBeDefined();
});
});describe('Data API', () => {
it('should create new data', async () => {
const response = await request(app)
.post('/api/data')
.send(mockData);
expect(response.status).toBe(201);
});
});/**
* Stores data in the repository
* @param {DataInput} data - The data to store
* @returns {Promise<Data>} The stored data
* @throws {AppError} If storage fails
*/
async store(data: DataInput): Promise<Data> {
// Implementation
}export interface DataInput {
content: any;
type: DataType;
metadata?: Record<string, any>;
}feat: add data encryption support
fix: resolve connection timeout issue
docs: update API documentation
test: add integration tests for data API
feature/data-encryption
bugfix/connection-timeout
docs/api-updates
test/integration-tests