Skip to main content
Glama
README.md5.5 kB
# Resource Creators - Strategy Pattern Implementation This directory implements the Strategy Pattern to handle different Attio resource types (companies, people, tasks, notes) in the `AttioCreateService`. This refactoring addresses Issue #552 by applying Single Responsibility Principle (SRP) and promoting maintainability. ## Architecture Overview ### Problem Addressed The original `AttioCreateService` violated SRP by handling multiple concerns within large methods: - `createCompany`: ~139 lines with mixed concerns - `createPerson`: ~168 lines with similar patterns - Mixed responsibilities: API normalization, error recovery, data extraction, validation ### Solution: Strategy Pattern Each resource type now has its own dedicated creator class that encapsulates: - Resource-specific normalization logic - API interaction patterns - Error handling and recovery strategies - Response processing ## File Structure ``` src/services/create/creators/ ├── README.md # This documentation ├── index.ts # Exports all creators and types ├── types.ts # Base interfaces and types ├── base-creator.ts # Abstract base class with shared utilities ├── company-creator.ts # Company-specific creation logic ├── person-creator.ts # Person-specific creation logic ├── task-creator.ts # Task-specific creation logic └── note-creator.ts # Note-specific creation logic ``` ## Core Components ### Base Interfaces (`types.ts`) - **`ResourceCreator`**: Base interface all creators must implement - **`ResourceCreatorContext`**: Shared context with client and utilities - **`RecoveryOptions`**: Configuration for error recovery strategies ### Abstract Base Class (`base-creator.ts`) **`BaseCreator`** provides common functionality: - Response processing and record extraction - ID enrichment from web_url - Generic recovery attempt handling - Enhanced error creation - Shared debugging and logging patterns ### Resource-Specific Creators #### CompanyCreator - Handles domain/domains normalization via `normalizeCompanyValues` - Recovery by domain search, then by name search - Specialized error handling for company creation #### PersonCreator - Handles name and email normalization via `normalizePersonValues` - Email format retry logic (string ↔ object format) - Recovery by primary email address search #### TaskCreator - Delegates to existing `tasks.js` object - Converts result to `AttioRecord` format via `convertTaskToAttioRecord` - Simplified strategy due to delegation approach #### NoteCreator - Delegates to existing `notes.js` object - Handles response unwrapping and normalization - Input validation for required note fields ## Usage Example ```typescript // The AttioCreateService now uses creators internally const service = new AttioCreateService(); // Each method delegates to the appropriate creator const company = await service.createCompany({ name: "Acme Corp", domain: "acme.com" }); ``` ## Benefits Achieved ### Single Responsibility Principle ✅ - Each creator has one reason to change - Clear separation between resource types - Focused error handling per resource ### Maintainability ✅ - Add new resource types by creating new creators - Modify resource logic without affecting others - Clear dependency injection through constructor ### Testability ✅ - Test each creator independently - Mock context for unit testing - Isolated error scenarios per resource ### Code Reuse ✅ - Shared utilities in `BaseCreator` - Common patterns extracted to base class - Reduced duplication across creators ## Extension Points ### Adding New Resource Types 1. Create new creator class extending `BaseCreator`: ```typescript export class NewResourceCreator extends BaseCreator { readonly resourceType = 'newresource'; readonly endpoint = '/objects/newresource/records'; async create(input: Record<string, unknown>, context: ResourceCreatorContext): Promise<AttioRecord> { // Implementation } } ``` 2. Register in `AttioCreateService`: ```typescript this.creators.set('newresource', new NewResourceCreator()); ``` 3. Add interface method: ```typescript async createNewResource(input: Record<string, unknown>): Promise<AttioRecord> { return this.getCreator('newresource').create(input, this.context); } ``` ### Customizing Recovery Strategies Override `getRecoveryOptions()` and `attemptRecovery()` in your creator: ```typescript protected getRecoveryOptions(): RecoveryOptions { return { searchFilters: [ { field: 'unique_field', value: '', operator: 'eq' } ], maxAttempts: 3 }; } ``` ## Migration Notes - Original `AttioCreateService` backed up to `.backup` file - All existing tests pass without modification - Public interface remains unchanged - Performance characteristics maintained - Error handling patterns preserved ## Compliance This implementation satisfies: - **Issue #552**: Strategy Pattern for SRP compliance - **80/20 Principle**: Maximum benefit with minimal complexity - **Existing API Contract**: No breaking changes - **Test Compatibility**: All existing tests pass ## Future Improvements 1. **Creator-Specific Tests**: Add unit tests for each creator (currently pending) 2. **Async Creator Registration**: Support dynamic creator loading 3. **Validation Pipeline**: Add creator-specific input validation 4. **Metrics Collection**: Add per-creator performance metrics

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kesslerio/attio-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server