fix: add missing domain ports files that were gitignored
Some checks failed
CI/CD Pipeline / Integration Tests (push) Blocked by required conditions
CI/CD Pipeline / Deployment Summary (push) Blocked by required conditions
CI/CD Pipeline / Backend - Build, Test & Push (push) Failing after 2m11s
CI/CD Pipeline / Frontend - Build, Test & Push (push) Has been cancelled
Some checks failed
CI/CD Pipeline / Integration Tests (push) Blocked by required conditions
CI/CD Pipeline / Deployment Summary (push) Blocked by required conditions
CI/CD Pipeline / Backend - Build, Test & Push (push) Failing after 2m11s
CI/CD Pipeline / Frontend - Build, Test & Push (push) Has been cancelled
Root cause: The .gitignore had 'out/' which was ignoring ALL directories named 'out', including 'src/domain/ports/out/' which contains critical port interfaces for hexagonal architecture. Changes: - Modified .gitignore to only ignore Next.js output directories - Added all 17 missing files from src/domain/ports/out/ - audit-log.repository.ts - booking.repository.ts - cache.port.ts - carrier-connector.port.ts - carrier.repository.ts - csv-booking.repository.ts - csv-rate-loader.port.ts - email.port.ts - index.ts - notification.repository.ts - organization.repository.ts - pdf.port.ts - port.repository.ts - rate-quote.repository.ts - storage.port.ts - user.repository.ts - webhook.repository.ts This resolves all "Cannot find module '@domain/ports/out/*'" TypeScript errors. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
62cad30fc2
commit
ee38ee6961
4
.gitignore
vendored
4
.gitignore
vendored
@ -12,7 +12,9 @@ coverage/
|
||||
dist/
|
||||
build/
|
||||
.next/
|
||||
out/
|
||||
# Only ignore Next.js output directory, not all 'out' folders
|
||||
/.next/out/
|
||||
/apps/frontend/out/
|
||||
|
||||
# Environment variables
|
||||
.env
|
||||
|
||||
59
apps/backend/src/domain/ports/out/audit-log.repository.ts
Normal file
59
apps/backend/src/domain/ports/out/audit-log.repository.ts
Normal file
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Audit Log Repository Port
|
||||
*
|
||||
* Defines the interface for Audit Log persistence operations.
|
||||
* This is a secondary port (output port) in hexagonal architecture.
|
||||
*/
|
||||
|
||||
import { AuditLog } from '../../entities/audit-log.entity';
|
||||
|
||||
export const AUDIT_LOG_REPOSITORY = 'AuditLogRepository';
|
||||
|
||||
export interface AuditLogFilters {
|
||||
userId?: string;
|
||||
organizationId?: string;
|
||||
action?: string[];
|
||||
resourceType?: string;
|
||||
resourceId?: string;
|
||||
dateFrom?: Date;
|
||||
dateTo?: Date;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}
|
||||
|
||||
export interface AuditLogRepository {
|
||||
/**
|
||||
* Save an audit log entry
|
||||
*/
|
||||
save(auditLog: AuditLog): Promise<void>;
|
||||
|
||||
/**
|
||||
* Find audit log by ID
|
||||
*/
|
||||
findById(id: string): Promise<AuditLog | null>;
|
||||
|
||||
/**
|
||||
* Find audit logs by filters
|
||||
*/
|
||||
findByFilters(filters: AuditLogFilters): Promise<AuditLog[]>;
|
||||
|
||||
/**
|
||||
* Count audit logs matching filters
|
||||
*/
|
||||
count(filters: AuditLogFilters): Promise<number>;
|
||||
|
||||
/**
|
||||
* Find audit logs for a specific resource
|
||||
*/
|
||||
findByResource(resourceType: string, resourceId: string): Promise<AuditLog[]>;
|
||||
|
||||
/**
|
||||
* Find recent audit logs for an organization
|
||||
*/
|
||||
findRecentByOrganization(organizationId: string, limit: number): Promise<AuditLog[]>;
|
||||
|
||||
/**
|
||||
* Find audit logs by user
|
||||
*/
|
||||
findByUser(userId: string, limit: number): Promise<AuditLog[]>;
|
||||
}
|
||||
49
apps/backend/src/domain/ports/out/booking.repository.ts
Normal file
49
apps/backend/src/domain/ports/out/booking.repository.ts
Normal file
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Booking Repository Port
|
||||
*
|
||||
* Defines the interface for Booking persistence operations.
|
||||
* This is a secondary port (output port) in hexagonal architecture.
|
||||
*/
|
||||
|
||||
import { Booking } from '../../entities/booking.entity';
|
||||
import { BookingNumber } from '../../value-objects/booking-number.vo';
|
||||
import { BookingStatus } from '../../value-objects/booking-status.vo';
|
||||
|
||||
export const BOOKING_REPOSITORY = 'BookingRepository';
|
||||
|
||||
export interface BookingRepository {
|
||||
/**
|
||||
* Save a booking entity
|
||||
*/
|
||||
save(booking: Booking): Promise<Booking>;
|
||||
|
||||
/**
|
||||
* Find booking by ID
|
||||
*/
|
||||
findById(id: string): Promise<Booking | null>;
|
||||
|
||||
/**
|
||||
* Find booking by booking number
|
||||
*/
|
||||
findByBookingNumber(bookingNumber: BookingNumber): Promise<Booking | null>;
|
||||
|
||||
/**
|
||||
* Find all bookings for a specific user
|
||||
*/
|
||||
findByUser(userId: string): Promise<Booking[]>;
|
||||
|
||||
/**
|
||||
* Find all bookings for an organization
|
||||
*/
|
||||
findByOrganization(organizationId: string): Promise<Booking[]>;
|
||||
|
||||
/**
|
||||
* Find all bookings with a specific status
|
||||
*/
|
||||
findByStatus(status: BookingStatus): Promise<Booking[]>;
|
||||
|
||||
/**
|
||||
* Delete booking by ID
|
||||
*/
|
||||
delete(id: string): Promise<void>;
|
||||
}
|
||||
60
apps/backend/src/domain/ports/out/cache.port.ts
Normal file
60
apps/backend/src/domain/ports/out/cache.port.ts
Normal file
@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Cache Port
|
||||
*
|
||||
* Defines the interface for caching operations.
|
||||
* This is a secondary port (output port) in hexagonal architecture.
|
||||
*/
|
||||
|
||||
export const CACHE_PORT = 'CachePort';
|
||||
|
||||
export interface CachePort {
|
||||
/**
|
||||
* Get a value from cache
|
||||
* Returns null if key doesn't exist
|
||||
*/
|
||||
get<T>(key: string): Promise<T | null>;
|
||||
|
||||
/**
|
||||
* Set a value in cache
|
||||
* @param key - Cache key
|
||||
* @param value - Value to store
|
||||
* @param ttlSeconds - Time to live in seconds (optional)
|
||||
*/
|
||||
set<T>(key: string, value: T, ttlSeconds?: number): Promise<void>;
|
||||
|
||||
/**
|
||||
* Delete a key from cache
|
||||
*/
|
||||
delete(key: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Delete multiple keys from cache
|
||||
*/
|
||||
deleteMany(keys: string[]): Promise<void>;
|
||||
|
||||
/**
|
||||
* Check if a key exists in cache
|
||||
*/
|
||||
exists(key: string): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Get time to live for a key (in seconds)
|
||||
* Returns -2 if key doesn't exist, -1 if key has no expiration
|
||||
*/
|
||||
ttl(key: string): Promise<number>;
|
||||
|
||||
/**
|
||||
* Clear all cache entries
|
||||
*/
|
||||
clear(): Promise<void>;
|
||||
|
||||
/**
|
||||
* Get cache statistics
|
||||
*/
|
||||
getStats(): Promise<{
|
||||
hits: number;
|
||||
misses: number;
|
||||
hitRate: number;
|
||||
keyCount: number;
|
||||
}>;
|
||||
}
|
||||
64
apps/backend/src/domain/ports/out/carrier-connector.port.ts
Normal file
64
apps/backend/src/domain/ports/out/carrier-connector.port.ts
Normal file
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Carrier Connector Port
|
||||
*
|
||||
* Defines the interface for carrier API integrations.
|
||||
* This is a secondary port (output port) in hexagonal architecture.
|
||||
*/
|
||||
|
||||
import { RateQuote } from '../../entities/rate-quote.entity';
|
||||
|
||||
export const CARRIER_CONNECTOR_PORT = 'CarrierConnectorPort';
|
||||
|
||||
export interface CarrierRateSearchInput {
|
||||
origin: string;
|
||||
destination: string;
|
||||
containerType: string;
|
||||
departureDate: Date;
|
||||
quantity?: number;
|
||||
mode?: string; // 'FCL' or 'LCL'
|
||||
weight?: number; // Weight in kg
|
||||
volume?: number; // Volume in CBM
|
||||
isHazmat?: boolean; // Hazardous materials flag
|
||||
imoClass?: string; // IMO class for hazmat
|
||||
hazardous?: boolean;
|
||||
reefer?: boolean;
|
||||
commodityType?: string;
|
||||
}
|
||||
|
||||
export interface CarrierAvailabilityInput {
|
||||
origin: string;
|
||||
destination: string;
|
||||
containerType: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
departureDate?: Date; // Specific departure date
|
||||
quantity?: number; // Number of containers
|
||||
}
|
||||
|
||||
export interface CarrierConnectorPort {
|
||||
/**
|
||||
* Get the carrier name
|
||||
*/
|
||||
getCarrierName(): string;
|
||||
|
||||
/**
|
||||
* Get the carrier code
|
||||
*/
|
||||
getCarrierCode(): string;
|
||||
|
||||
/**
|
||||
* Search for shipping rates
|
||||
*/
|
||||
searchRates(input: CarrierRateSearchInput): Promise<RateQuote[]>;
|
||||
|
||||
/**
|
||||
* Check container availability
|
||||
* Returns the number of available containers
|
||||
*/
|
||||
checkAvailability(input: CarrierAvailabilityInput): Promise<number>;
|
||||
|
||||
/**
|
||||
* Health check to verify carrier API is accessible
|
||||
*/
|
||||
healthCheck(): Promise<boolean>;
|
||||
}
|
||||
62
apps/backend/src/domain/ports/out/carrier.repository.ts
Normal file
62
apps/backend/src/domain/ports/out/carrier.repository.ts
Normal file
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Carrier Repository Port
|
||||
*
|
||||
* Defines the interface for Carrier persistence operations.
|
||||
* This is a secondary port (output port) in hexagonal architecture.
|
||||
*/
|
||||
|
||||
import { Carrier } from '../../entities/carrier.entity';
|
||||
|
||||
export const CARRIER_REPOSITORY = 'CarrierRepository';
|
||||
|
||||
export interface CarrierRepository {
|
||||
/**
|
||||
* Save a carrier entity
|
||||
*/
|
||||
save(carrier: Carrier): Promise<Carrier>;
|
||||
|
||||
/**
|
||||
* Save multiple carrier entities
|
||||
*/
|
||||
saveMany(carriers: Carrier[]): Promise<Carrier[]>;
|
||||
|
||||
/**
|
||||
* Find carrier by ID
|
||||
*/
|
||||
findById(id: string): Promise<Carrier | null>;
|
||||
|
||||
/**
|
||||
* Find carrier by carrier code
|
||||
*/
|
||||
findByCode(code: string): Promise<Carrier | null>;
|
||||
|
||||
/**
|
||||
* Find carrier by SCAC (Standard Carrier Alpha Code)
|
||||
*/
|
||||
findByScac(scac: string): Promise<Carrier | null>;
|
||||
|
||||
/**
|
||||
* Find all active carriers
|
||||
*/
|
||||
findAllActive(): Promise<Carrier[]>;
|
||||
|
||||
/**
|
||||
* Find all carriers that support API integration
|
||||
*/
|
||||
findWithApiSupport(): Promise<Carrier[]>;
|
||||
|
||||
/**
|
||||
* Find all carriers (including inactive)
|
||||
*/
|
||||
findAll(): Promise<Carrier[]>;
|
||||
|
||||
/**
|
||||
* Update a carrier entity
|
||||
*/
|
||||
update(carrier: Carrier): Promise<Carrier>;
|
||||
|
||||
/**
|
||||
* Delete carrier by ID
|
||||
*/
|
||||
deleteById(id: string): Promise<void>;
|
||||
}
|
||||
87
apps/backend/src/domain/ports/out/csv-booking.repository.ts
Normal file
87
apps/backend/src/domain/ports/out/csv-booking.repository.ts
Normal file
@ -0,0 +1,87 @@
|
||||
import { CsvBooking } from '../../entities/csv-booking.entity';
|
||||
|
||||
/**
|
||||
* CSV Booking Repository Port (Output Port)
|
||||
*
|
||||
* Interface for CSV booking persistence operations.
|
||||
* Implemented by infrastructure layer.
|
||||
*
|
||||
* This port abstracts database operations from the domain layer.
|
||||
*/
|
||||
export interface CsvBookingRepositoryPort {
|
||||
/**
|
||||
* Create a new booking
|
||||
* @param booking - Booking to create
|
||||
* @returns Created booking with generated ID
|
||||
*/
|
||||
create(booking: CsvBooking): Promise<CsvBooking>;
|
||||
|
||||
/**
|
||||
* Find booking by ID
|
||||
* @param id - Booking ID
|
||||
* @returns Booking if found, null otherwise
|
||||
*/
|
||||
findById(id: string): Promise<CsvBooking | null>;
|
||||
|
||||
/**
|
||||
* Find booking by confirmation token
|
||||
* @param token - Confirmation token from email link
|
||||
* @returns Booking if found, null otherwise
|
||||
*/
|
||||
findByToken(token: string): Promise<CsvBooking | null>;
|
||||
|
||||
/**
|
||||
* Find all bookings for a user
|
||||
* @param userId - User ID
|
||||
* @returns Array of bookings
|
||||
*/
|
||||
findByUserId(userId: string): Promise<CsvBooking[]>;
|
||||
|
||||
/**
|
||||
* Find all bookings for an organization
|
||||
* @param organizationId - Organization ID
|
||||
* @returns Array of bookings
|
||||
*/
|
||||
findByOrganizationId(organizationId: string): Promise<CsvBooking[]>;
|
||||
|
||||
/**
|
||||
* Find bookings by status
|
||||
* @param status - Booking status
|
||||
* @returns Array of bookings with matching status
|
||||
*/
|
||||
findByStatus(status: string): Promise<CsvBooking[]>;
|
||||
|
||||
/**
|
||||
* Find pending bookings that are about to expire
|
||||
* @param daysUntilExpiration - Number of days until expiration (e.g., 2)
|
||||
* @returns Array of bookings expiring soon
|
||||
*/
|
||||
findExpiringSoon(daysUntilExpiration: number): Promise<CsvBooking[]>;
|
||||
|
||||
/**
|
||||
* Update existing booking
|
||||
* @param booking - Booking with updated data
|
||||
* @returns Updated booking
|
||||
*/
|
||||
update(booking: CsvBooking): Promise<CsvBooking>;
|
||||
|
||||
/**
|
||||
* Delete booking
|
||||
* @param id - Booking ID
|
||||
*/
|
||||
delete(id: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Count bookings by status for a user
|
||||
* @param userId - User ID
|
||||
* @returns Object with counts per status
|
||||
*/
|
||||
countByStatusForUser(userId: string): Promise<Record<string, number>>;
|
||||
|
||||
/**
|
||||
* Count bookings by status for an organization
|
||||
* @param organizationId - Organization ID
|
||||
* @returns Object with counts per status
|
||||
*/
|
||||
countByStatusForOrganization(organizationId: string): Promise<Record<string, number>>;
|
||||
}
|
||||
44
apps/backend/src/domain/ports/out/csv-rate-loader.port.ts
Normal file
44
apps/backend/src/domain/ports/out/csv-rate-loader.port.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { CsvRate } from '../../entities/csv-rate.entity';
|
||||
|
||||
/**
|
||||
* CSV Rate Loader Port (Output Port)
|
||||
*
|
||||
* Interface for loading rates from CSV files.
|
||||
* Implemented by infrastructure layer.
|
||||
*
|
||||
* This port abstracts CSV file operations from the domain layer.
|
||||
*/
|
||||
export interface CsvRateLoaderPort {
|
||||
/**
|
||||
* Load all rates from a CSV file
|
||||
* @param filePath - Absolute or relative path to CSV file
|
||||
* @param companyEmail - Email address for the company (stored in config metadata)
|
||||
* @returns Array of CSV rates
|
||||
* @throws Error if file cannot be read or parsed
|
||||
*/
|
||||
loadRatesFromCsv(filePath: string, companyEmail: string): Promise<CsvRate[]>;
|
||||
|
||||
/**
|
||||
* Load rates for a specific company
|
||||
* @param companyName - Name of the carrier company
|
||||
* @returns Array of CSV rates for the company
|
||||
*/
|
||||
loadRatesByCompany(companyName: string): Promise<CsvRate[]>;
|
||||
|
||||
/**
|
||||
* Validate CSV file structure without fully parsing
|
||||
* @param filePath - Path to CSV file
|
||||
* @returns Validation result with errors if any
|
||||
*/
|
||||
validateCsvFile(filePath: string): Promise<{
|
||||
valid: boolean;
|
||||
errors: string[];
|
||||
rowCount?: number;
|
||||
}>;
|
||||
|
||||
/**
|
||||
* Get list of all available CSV rate files
|
||||
* @returns Array of file paths
|
||||
*/
|
||||
getAvailableCsvFiles(): Promise<string[]>;
|
||||
}
|
||||
92
apps/backend/src/domain/ports/out/email.port.ts
Normal file
92
apps/backend/src/domain/ports/out/email.port.ts
Normal file
@ -0,0 +1,92 @@
|
||||
/**
|
||||
* Email Port
|
||||
*
|
||||
* Defines the interface for email sending operations.
|
||||
* This is a secondary port (output port) in hexagonal architecture.
|
||||
*/
|
||||
|
||||
export const EMAIL_PORT = 'EmailPort';
|
||||
|
||||
export interface EmailAttachment {
|
||||
filename: string;
|
||||
content: Buffer | string;
|
||||
contentType?: string;
|
||||
}
|
||||
|
||||
export interface EmailOptions {
|
||||
to: string | string[];
|
||||
cc?: string | string[];
|
||||
bcc?: string | string[];
|
||||
replyTo?: string;
|
||||
subject: string;
|
||||
html?: string;
|
||||
text?: string;
|
||||
attachments?: EmailAttachment[];
|
||||
}
|
||||
|
||||
export interface EmailPort {
|
||||
/**
|
||||
* Send an email
|
||||
*/
|
||||
send(options: EmailOptions): Promise<void>;
|
||||
|
||||
/**
|
||||
* Send booking confirmation email
|
||||
*/
|
||||
sendBookingConfirmation(
|
||||
email: string,
|
||||
bookingNumber: string,
|
||||
bookingDetails: any,
|
||||
pdfAttachment?: Buffer
|
||||
): Promise<void>;
|
||||
|
||||
/**
|
||||
* Send email verification email
|
||||
*/
|
||||
sendVerificationEmail(email: string, token: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Send password reset email
|
||||
*/
|
||||
sendPasswordResetEmail(email: string, token: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Send welcome email
|
||||
*/
|
||||
sendWelcomeEmail(email: string, firstName: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Send user invitation email
|
||||
*/
|
||||
sendUserInvitation(
|
||||
email: string,
|
||||
organizationName: string,
|
||||
inviterName: string,
|
||||
tempPassword: string
|
||||
): Promise<void>;
|
||||
|
||||
/**
|
||||
* Send CSV booking request email to carrier
|
||||
*/
|
||||
sendCsvBookingRequest(
|
||||
carrierEmail: string,
|
||||
bookingDetails: {
|
||||
bookingId: string;
|
||||
origin: string;
|
||||
destination: string;
|
||||
volumeCBM: number;
|
||||
weightKG: number;
|
||||
palletCount: number;
|
||||
priceUSD: number;
|
||||
priceEUR: number;
|
||||
primaryCurrency: string;
|
||||
transitDays: number;
|
||||
containerType: string;
|
||||
documents: Array<{
|
||||
type: string;
|
||||
fileName: string;
|
||||
}>;
|
||||
confirmationToken: string;
|
||||
}
|
||||
): Promise<void>;
|
||||
}
|
||||
25
apps/backend/src/domain/ports/out/index.ts
Normal file
25
apps/backend/src/domain/ports/out/index.ts
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Domain Ports (Output) - Barrel Export
|
||||
*
|
||||
* Exports all output port interfaces and tokens for easy importing.
|
||||
*/
|
||||
|
||||
// Repository Ports
|
||||
export * from './user.repository';
|
||||
export * from './booking.repository';
|
||||
export * from './rate-quote.repository';
|
||||
export * from './organization.repository';
|
||||
export * from './port.repository';
|
||||
export * from './carrier.repository';
|
||||
export * from './notification.repository';
|
||||
export * from './audit-log.repository';
|
||||
export * from './webhook.repository';
|
||||
export * from './csv-booking.repository';
|
||||
|
||||
// Infrastructure Ports
|
||||
export * from './cache.port';
|
||||
export * from './email.port';
|
||||
export * from './pdf.port';
|
||||
export * from './storage.port';
|
||||
export * from './carrier-connector.port';
|
||||
export * from './csv-rate-loader.port';
|
||||
80
apps/backend/src/domain/ports/out/notification.repository.ts
Normal file
80
apps/backend/src/domain/ports/out/notification.repository.ts
Normal file
@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Notification Repository Port
|
||||
*
|
||||
* Defines the interface for Notification persistence operations.
|
||||
* This is a secondary port (output port) in hexagonal architecture.
|
||||
*/
|
||||
|
||||
import { Notification } from '../../entities/notification.entity';
|
||||
|
||||
export const NOTIFICATION_REPOSITORY = 'NotificationRepository';
|
||||
|
||||
export interface NotificationFilters {
|
||||
userId?: string;
|
||||
organizationId?: string;
|
||||
type?: string[];
|
||||
read?: boolean;
|
||||
priority?: string[];
|
||||
startDate?: Date;
|
||||
endDate?: Date;
|
||||
offset?: number;
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
export interface NotificationRepository {
|
||||
/**
|
||||
* Save a notification entity
|
||||
*/
|
||||
save(notification: Notification): Promise<void>;
|
||||
|
||||
/**
|
||||
* Find notification by ID
|
||||
*/
|
||||
findById(id: string): Promise<Notification | null>;
|
||||
|
||||
/**
|
||||
* Find notifications by filters
|
||||
*/
|
||||
findByFilters(filters: NotificationFilters): Promise<Notification[]>;
|
||||
|
||||
/**
|
||||
* Count notifications matching filters
|
||||
*/
|
||||
count(filters: NotificationFilters): Promise<number>;
|
||||
|
||||
/**
|
||||
* Find unread notifications for a user
|
||||
*/
|
||||
findUnreadByUser(userId: string, limit?: number): Promise<Notification[]>;
|
||||
|
||||
/**
|
||||
* Count unread notifications for a user
|
||||
*/
|
||||
countUnreadByUser(userId: string): Promise<number>;
|
||||
|
||||
/**
|
||||
* Find recent notifications for a user
|
||||
*/
|
||||
findRecentByUser(userId: string, limit?: number): Promise<Notification[]>;
|
||||
|
||||
/**
|
||||
* Mark a notification as read
|
||||
*/
|
||||
markAsRead(id: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Mark all notifications as read for a user
|
||||
*/
|
||||
markAllAsReadForUser(userId: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Delete a notification
|
||||
*/
|
||||
delete(id: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Delete old read notifications
|
||||
* Returns the number of deleted records
|
||||
*/
|
||||
deleteOldReadNotifications(olderThanDays: number): Promise<number>;
|
||||
}
|
||||
62
apps/backend/src/domain/ports/out/organization.repository.ts
Normal file
62
apps/backend/src/domain/ports/out/organization.repository.ts
Normal file
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Organization Repository Port
|
||||
*
|
||||
* Defines the interface for Organization persistence operations.
|
||||
* This is a secondary port (output port) in hexagonal architecture.
|
||||
*/
|
||||
|
||||
import { Organization } from '../../entities/organization.entity';
|
||||
|
||||
export const ORGANIZATION_REPOSITORY = 'OrganizationRepository';
|
||||
|
||||
export interface OrganizationRepository {
|
||||
/**
|
||||
* Save an organization entity
|
||||
*/
|
||||
save(organization: Organization): Promise<Organization>;
|
||||
|
||||
/**
|
||||
* Find organization by ID
|
||||
*/
|
||||
findById(id: string): Promise<Organization | null>;
|
||||
|
||||
/**
|
||||
* Find organization by name
|
||||
*/
|
||||
findByName(name: string): Promise<Organization | null>;
|
||||
|
||||
/**
|
||||
* Find organization by SCAC (Standard Carrier Alpha Code)
|
||||
*/
|
||||
findBySCAC(scac: string): Promise<Organization | null>;
|
||||
|
||||
/**
|
||||
* Find all organizations
|
||||
*/
|
||||
findAll(): Promise<Organization[]>;
|
||||
|
||||
/**
|
||||
* Find all active organizations
|
||||
*/
|
||||
findAllActive(): Promise<Organization[]>;
|
||||
|
||||
/**
|
||||
* Find organizations by type (e.g., 'FREIGHT_FORWARDER', 'CARRIER')
|
||||
*/
|
||||
findByType(type: string): Promise<Organization[]>;
|
||||
|
||||
/**
|
||||
* Update an organization entity
|
||||
*/
|
||||
update(organization: Organization): Promise<Organization>;
|
||||
|
||||
/**
|
||||
* Delete organization by ID
|
||||
*/
|
||||
deleteById(id: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Count total organizations
|
||||
*/
|
||||
count(): Promise<number>;
|
||||
}
|
||||
66
apps/backend/src/domain/ports/out/pdf.port.ts
Normal file
66
apps/backend/src/domain/ports/out/pdf.port.ts
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* PDF Port
|
||||
*
|
||||
* Defines the interface for PDF generation operations.
|
||||
* This is a secondary port (output port) in hexagonal architecture.
|
||||
*/
|
||||
|
||||
export const PDF_PORT = 'PdfPort';
|
||||
|
||||
export interface BookingPdfData {
|
||||
bookingNumber: string;
|
||||
bookingDate: Date;
|
||||
origin: {
|
||||
code: string;
|
||||
name: string;
|
||||
};
|
||||
destination: {
|
||||
code: string;
|
||||
name: string;
|
||||
};
|
||||
carrier: {
|
||||
name: string;
|
||||
logo?: string;
|
||||
};
|
||||
etd: Date;
|
||||
eta: Date;
|
||||
transitDays: number;
|
||||
shipper: {
|
||||
name: string;
|
||||
address: string;
|
||||
contact: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
};
|
||||
consignee: {
|
||||
name: string;
|
||||
address: string;
|
||||
contact: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
};
|
||||
containers: Array<{
|
||||
type: string;
|
||||
quantity: number;
|
||||
containerNumber?: string;
|
||||
sealNumber?: string;
|
||||
}>;
|
||||
cargoDescription: string;
|
||||
specialInstructions?: string;
|
||||
price: {
|
||||
amount: number;
|
||||
currency: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface PdfPort {
|
||||
/**
|
||||
* Generate booking confirmation PDF
|
||||
*/
|
||||
generateBookingConfirmation(data: BookingPdfData): Promise<Buffer>;
|
||||
|
||||
/**
|
||||
* Generate rate quote comparison PDF
|
||||
*/
|
||||
generateRateQuoteComparison(quotes: any[]): Promise<Buffer>;
|
||||
}
|
||||
58
apps/backend/src/domain/ports/out/port.repository.ts
Normal file
58
apps/backend/src/domain/ports/out/port.repository.ts
Normal file
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Port Repository Port
|
||||
*
|
||||
* Defines the interface for Port (maritime port) persistence operations.
|
||||
* This is a secondary port (output port) in hexagonal architecture.
|
||||
*/
|
||||
|
||||
import { Port } from '../../entities/port.entity';
|
||||
|
||||
export const PORT_REPOSITORY = 'PortRepository';
|
||||
|
||||
export interface PortRepository {
|
||||
/**
|
||||
* Save a port entity
|
||||
*/
|
||||
save(port: Port): Promise<Port>;
|
||||
|
||||
/**
|
||||
* Save multiple port entities
|
||||
*/
|
||||
saveMany(ports: Port[]): Promise<Port[]>;
|
||||
|
||||
/**
|
||||
* Find port by UN LOCODE
|
||||
*/
|
||||
findByCode(code: string): Promise<Port | null>;
|
||||
|
||||
/**
|
||||
* Find multiple ports by codes
|
||||
*/
|
||||
findByCodes(codes: string[]): Promise<Port[]>;
|
||||
|
||||
/**
|
||||
* Search ports by query string (name, city, or code)
|
||||
* with optional country filter and limit
|
||||
*/
|
||||
search(query: string, limit?: number, countryFilter?: string): Promise<Port[]>;
|
||||
|
||||
/**
|
||||
* Find all active ports
|
||||
*/
|
||||
findAllActive(): Promise<Port[]>;
|
||||
|
||||
/**
|
||||
* Find all ports in a specific country
|
||||
*/
|
||||
findByCountry(countryCode: string): Promise<Port[]>;
|
||||
|
||||
/**
|
||||
* Count total ports
|
||||
*/
|
||||
count(): Promise<number>;
|
||||
|
||||
/**
|
||||
* Delete port by code
|
||||
*/
|
||||
deleteByCode(code: string): Promise<void>;
|
||||
}
|
||||
53
apps/backend/src/domain/ports/out/rate-quote.repository.ts
Normal file
53
apps/backend/src/domain/ports/out/rate-quote.repository.ts
Normal file
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* RateQuote Repository Port
|
||||
*
|
||||
* Defines the interface for RateQuote persistence operations.
|
||||
* This is a secondary port (output port) in hexagonal architecture.
|
||||
*/
|
||||
|
||||
import { RateQuote } from '../../entities/rate-quote.entity';
|
||||
|
||||
export const RATE_QUOTE_REPOSITORY = 'RateQuoteRepository';
|
||||
|
||||
export interface RateQuoteRepository {
|
||||
/**
|
||||
* Save a rate quote entity
|
||||
*/
|
||||
save(rateQuote: RateQuote): Promise<RateQuote>;
|
||||
|
||||
/**
|
||||
* Save multiple rate quote entities
|
||||
*/
|
||||
saveMany(rateQuotes: RateQuote[]): Promise<RateQuote[]>;
|
||||
|
||||
/**
|
||||
* Find rate quote by ID
|
||||
*/
|
||||
findById(id: string): Promise<RateQuote | null>;
|
||||
|
||||
/**
|
||||
* Find rate quotes by search criteria
|
||||
*/
|
||||
findBySearchCriteria(criteria: {
|
||||
origin: string;
|
||||
destination: string;
|
||||
containerType: string;
|
||||
departureDate: Date;
|
||||
}): Promise<RateQuote[]>;
|
||||
|
||||
/**
|
||||
* Find all rate quotes for a specific carrier
|
||||
*/
|
||||
findByCarrier(carrierId: string): Promise<RateQuote[]>;
|
||||
|
||||
/**
|
||||
* Delete expired rate quotes
|
||||
* Returns the number of deleted records
|
||||
*/
|
||||
deleteExpired(): Promise<number>;
|
||||
|
||||
/**
|
||||
* Delete rate quote by ID
|
||||
*/
|
||||
deleteById(id: string): Promise<void>;
|
||||
}
|
||||
69
apps/backend/src/domain/ports/out/storage.port.ts
Normal file
69
apps/backend/src/domain/ports/out/storage.port.ts
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Storage Port
|
||||
*
|
||||
* Defines the interface for object storage operations (S3, MinIO, etc.).
|
||||
* This is a secondary port (output port) in hexagonal architecture.
|
||||
*/
|
||||
|
||||
export const STORAGE_PORT = 'StoragePort';
|
||||
|
||||
export interface UploadOptions {
|
||||
bucket: string;
|
||||
key: string;
|
||||
body: Buffer | string;
|
||||
contentType?: string;
|
||||
metadata?: Record<string, string>;
|
||||
acl?: string;
|
||||
}
|
||||
|
||||
export interface DownloadOptions {
|
||||
bucket: string;
|
||||
key: string;
|
||||
}
|
||||
|
||||
export interface DeleteOptions {
|
||||
bucket: string;
|
||||
key: string;
|
||||
}
|
||||
|
||||
export interface StorageObject {
|
||||
key: string;
|
||||
url: string;
|
||||
size: number;
|
||||
contentType?: string;
|
||||
lastModified?: Date;
|
||||
}
|
||||
|
||||
export interface StoragePort {
|
||||
/**
|
||||
* Upload a file to storage
|
||||
*/
|
||||
upload(options: UploadOptions): Promise<StorageObject>;
|
||||
|
||||
/**
|
||||
* Download a file from storage
|
||||
*/
|
||||
download(options: DownloadOptions): Promise<Buffer>;
|
||||
|
||||
/**
|
||||
* Delete a file from storage
|
||||
*/
|
||||
delete(options: DeleteOptions): Promise<void>;
|
||||
|
||||
/**
|
||||
* Get a signed URL for temporary access
|
||||
* @param options - Download options
|
||||
* @param expiresIn - URL expiration in seconds (default: 3600)
|
||||
*/
|
||||
getSignedUrl(options: DownloadOptions, expiresIn?: number): Promise<string>;
|
||||
|
||||
/**
|
||||
* Check if a file exists in storage
|
||||
*/
|
||||
exists(options: DownloadOptions): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* List objects in a bucket
|
||||
*/
|
||||
list(bucket: string, prefix?: string): Promise<StorageObject[]>;
|
||||
}
|
||||
62
apps/backend/src/domain/ports/out/user.repository.ts
Normal file
62
apps/backend/src/domain/ports/out/user.repository.ts
Normal file
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* User Repository Port
|
||||
*
|
||||
* Defines the interface for User persistence operations.
|
||||
* This is a secondary port (output port) in hexagonal architecture.
|
||||
*/
|
||||
|
||||
import { User } from '../../entities/user.entity';
|
||||
|
||||
export const USER_REPOSITORY = 'UserRepository';
|
||||
|
||||
export interface UserRepository {
|
||||
/**
|
||||
* Save a user entity
|
||||
*/
|
||||
save(user: User): Promise<User>;
|
||||
|
||||
/**
|
||||
* Find user by ID
|
||||
*/
|
||||
findById(id: string): Promise<User | null>;
|
||||
|
||||
/**
|
||||
* Find user by email address
|
||||
*/
|
||||
findByEmail(email: string): Promise<User | null>;
|
||||
|
||||
/**
|
||||
* Find all users belonging to an organization
|
||||
*/
|
||||
findByOrganization(organizationId: string): Promise<User[]>;
|
||||
|
||||
/**
|
||||
* Find all users with a specific role
|
||||
*/
|
||||
findByRole(role: string): Promise<User[]>;
|
||||
|
||||
/**
|
||||
* Find all active users
|
||||
*/
|
||||
findAllActive(): Promise<User[]>;
|
||||
|
||||
/**
|
||||
* Update a user entity
|
||||
*/
|
||||
update(user: User): Promise<User>;
|
||||
|
||||
/**
|
||||
* Delete user by ID
|
||||
*/
|
||||
deleteById(id: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Count users in an organization
|
||||
*/
|
||||
countByOrganization(organizationId: string): Promise<number>;
|
||||
|
||||
/**
|
||||
* Check if email exists
|
||||
*/
|
||||
emailExists(email: string): Promise<boolean>;
|
||||
}
|
||||
53
apps/backend/src/domain/ports/out/webhook.repository.ts
Normal file
53
apps/backend/src/domain/ports/out/webhook.repository.ts
Normal file
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Webhook Repository Port
|
||||
*
|
||||
* Defines the interface for Webhook persistence operations.
|
||||
* This is a secondary port (output port) in hexagonal architecture.
|
||||
*/
|
||||
|
||||
import { Webhook, WebhookEvent } from '../../entities/webhook.entity';
|
||||
|
||||
export const WEBHOOK_REPOSITORY = 'WebhookRepository';
|
||||
|
||||
export interface WebhookFilters {
|
||||
organizationId?: string;
|
||||
status?: string[];
|
||||
event?: WebhookEvent;
|
||||
}
|
||||
|
||||
export interface WebhookRepository {
|
||||
/**
|
||||
* Save a webhook entity
|
||||
*/
|
||||
save(webhook: Webhook): Promise<void>;
|
||||
|
||||
/**
|
||||
* Find webhook by ID
|
||||
*/
|
||||
findById(id: string): Promise<Webhook | null>;
|
||||
|
||||
/**
|
||||
* Find all webhooks for an organization
|
||||
*/
|
||||
findByOrganization(organizationId: string): Promise<Webhook[]>;
|
||||
|
||||
/**
|
||||
* Find active webhooks by event and organization
|
||||
*/
|
||||
findActiveByEvent(event: WebhookEvent, organizationId: string): Promise<Webhook[]>;
|
||||
|
||||
/**
|
||||
* Find webhooks by filters
|
||||
*/
|
||||
findByFilters(filters: WebhookFilters): Promise<Webhook[]>;
|
||||
|
||||
/**
|
||||
* Delete a webhook
|
||||
*/
|
||||
delete(id: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Count webhooks for an organization
|
||||
*/
|
||||
countByOrganization(organizationId: string): Promise<number>;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user