xpeditis2.0/apps/backend/src/domain/services/port-search.service.ts
2025-10-20 12:30:08 +02:00

66 lines
1.8 KiB
TypeScript

/**
* PortSearchService
*
* Domain service for port search and autocomplete
*
* Business Rules:
* - Fuzzy search on port name, city, and code
* - Return top 10 results by default
* - Support country filtering
*/
import { Port } from '../entities/port.entity';
import { GetPortsPort, PortSearchInput, PortSearchOutput, GetPortInput } from '../ports/in/get-ports.port';
import { PortRepository } from '../ports/out/port.repository';
import { PortNotFoundException } from '../exceptions/port-not-found.exception';
export class PortSearchService implements GetPortsPort {
private static readonly DEFAULT_LIMIT = 10;
constructor(private readonly portRepository: PortRepository) {}
async search(input: PortSearchInput): Promise<PortSearchOutput> {
const limit = input.limit || PortSearchService.DEFAULT_LIMIT;
const query = input.query.trim();
if (query.length === 0) {
return {
ports: [],
totalMatches: 0,
};
}
// Search using repository fuzzy search
const ports = await this.portRepository.search(query, limit, input.countryFilter);
return {
ports,
totalMatches: ports.length,
};
}
async getByCode(input: GetPortInput): Promise<Port> {
const port = await this.portRepository.findByCode(input.portCode);
if (!port) {
throw new PortNotFoundException(input.portCode);
}
return port;
}
async getByCodes(portCodes: string[]): Promise<Port[]> {
const ports = await this.portRepository.findByCodes(portCodes);
// Check if all ports were found
const foundCodes = ports.map((p) => p.code);
const missingCodes = portCodes.filter((code) => !foundCodes.includes(code));
if (missingCodes.length > 0) {
throw new PortNotFoundException(missingCodes[0]);
}
return ports;
}
}