xpeditis2.0/apps/backend/src/infrastructure/carriers/msc/msc.connector.ts
David 2c2b7b2a11
Some checks failed
CI/CD Pipeline - Xpeditis PreProd / Run Smoke Tests (push) Blocked by required conditions
CI/CD Pipeline - Xpeditis PreProd / Deploy to PreProd Server (push) Blocked by required conditions
CI/CD Pipeline - Xpeditis PreProd / Backend - Build & Test (push) Failing after 5m50s
CI/CD Pipeline - Xpeditis PreProd / Backend - Docker Build & Push (push) Has been skipped
CI/CD Pipeline - Xpeditis PreProd / Frontend - Build & Test (push) Successful in 10m56s
CI/CD Pipeline - Xpeditis PreProd / Frontend - Docker Build & Push (push) Has been cancelled
fix: convert TypeScript path aliases to relative imports for CI/CD compatibility
Replace all @domain/ports/out/* imports with relative paths to fix TypeScript
compilation errors in CI/CD environment.

The issue was that TypeScript compiler (tsc) used by nest build doesn't
resolve path aliases by default. While tsconfig-paths works at runtime and
in development, it doesn't help during compilation.

Changes:
- Convert @domain/ports/out/* to relative paths (../../domain/ports/out/, etc.)
- Remove tsc-alias dependency (no longer needed)
- Revert build script to "nest build" only

This ensures the build works consistently in both local and CI/CD environments.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-16 02:59:52 +01:00

107 lines
3.3 KiB
TypeScript

/**
* MSC (Mediterranean Shipping Company) Connector
*
* Implements CarrierConnectorPort for MSC API integration
*/
import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import {
CarrierConnectorPort,
CarrierRateSearchInput,
CarrierAvailabilityInput,
} from '../../../domain/ports/out/carrier-connector.port';
import { RateQuote } from '../../../domain/entities/rate-quote.entity';
import { BaseCarrierConnector, CarrierConfig } from '../base-carrier.connector';
import { MSCRequestMapper } from './msc.mapper';
@Injectable()
export class MSCConnectorAdapter extends BaseCarrierConnector implements CarrierConnectorPort {
private readonly apiUrl: string;
private readonly apiKey: string;
constructor(
private readonly configService: ConfigService,
private readonly requestMapper: MSCRequestMapper
) {
const config: CarrierConfig = {
name: 'MSC',
code: 'MSCU',
baseUrl: configService.get<string>('MSC_API_URL', 'https://api.msc.com/v1'),
timeout: 5000,
maxRetries: 3,
circuitBreakerThreshold: 50,
circuitBreakerTimeout: 30000,
};
super(config);
this.apiUrl = config.baseUrl;
this.apiKey = this.configService.get<string>('MSC_API_KEY', '');
}
async searchRates(input: CarrierRateSearchInput): Promise<RateQuote[]> {
this.logger.log(`Searching MSC rates: ${input.origin} -> ${input.destination}`);
try {
// Map internal format to MSC API format
const mscRequest = this.requestMapper.toMSCRequest(input);
// Make API call with circuit breaker
const response = await this.makeRequest({
url: `${this.apiUrl}/rates/search`,
method: 'POST',
data: mscRequest,
headers: {
'X-API-Key': this.apiKey,
'Content-Type': 'application/json',
},
});
// Map MSC response to domain entities
const rateQuotes = this.requestMapper.fromMSCResponse(response.data, input);
this.logger.log(`Found ${rateQuotes.length} MSC rates`);
return rateQuotes;
} catch (error: any) {
this.logger.error(`MSC API error: ${error?.message || 'Unknown error'}`);
// Handle specific MSC error codes
if (error?.response?.status === 404) {
this.logger.warn('No MSC rates found for this route');
return [];
}
if (error?.response?.status === 429) {
this.logger.error('MSC rate limit exceeded');
throw new Error('MSC_RATE_LIMIT_EXCEEDED');
}
// Return empty array on error (fail gracefully)
return [];
}
}
async checkAvailability(input: CarrierAvailabilityInput): Promise<number> {
try {
const response = await this.makeRequest({
url: `${this.apiUrl}/availability/check`,
method: 'POST',
data: {
origin: input.origin,
destination: input.destination,
departure_date: input.departureDate,
container_type: input.containerType,
quantity: input.quantity,
},
headers: {
'X-API-Key': this.apiKey,
},
});
return (response.data as any).available_slots || 0;
} catch (error: any) {
this.logger.error(`MSC availability check error: ${error?.message || 'Unknown error'}`);
return 0;
}
}
}