UNPKG

@invoiceddd/application

Version:

Application layer for the InvoiceDDD system - use cases and application services

756 lines (743 loc) 29.8 kB
import { Invoice, RepositoryError, Order, AllDomainEvents, InvoiceConfig, CustomerInfo, OrderItem, InvoiceFinancials, InvoiceAggregate, InvoiceCreated, InvoiceValidationError, InvoiceNumberFormatError, InvoiceNumberConflictError as InvoiceNumberConflictError$1, InvoiceNumberFormatValidator, PDFRenderer, FinancialCalculationService, ShippingPolicy } from '@invoiceddd/domain'; import { Effect, Option, Context, Layer } from 'effect'; import * as effect_Cause from 'effect/Cause'; import * as effect_Types from 'effect/Types'; /** * Filters for querying invoices * @since 0.1.0 */ interface InvoiceFilters { readonly invoiceNumber?: string; readonly dateFrom?: Date; readonly dateTo?: Date; readonly minTotal?: number; readonly maxTotal?: number; readonly createdBy?: string; } /** * Pagination parameters * @since 0.1.0 */ interface Pagination { readonly page: number; readonly limit: number; } /** * Paginated result for invoice queries * @since 0.1.0 */ interface PaginatedInvoices { readonly invoices: readonly Invoice[]; readonly totalCount: number; readonly page: number; readonly limit: number; readonly totalPages: number; } /** * Repository interface for Invoice operations. * This port defines the contract for invoice persistence operations. * * @interface InvoiceRepository * @since 0.1.0 * @see {@link RepositoryError} * @see {@link Invoice} * @see {@link InvoiceFilters} * @see {@link PaginatedInvoices} * @example * import { InvoiceRepository } from '@invoiceddd/application'; * // Inject implementation at runtime */ interface InvoiceRepositorySchema { /** * Save an invoice to the repository. * @param invoice The invoice to save * @returns Effect that resolves when save is complete * @since 0.1.0 * @example * await invoiceRepository.save(invoice) */ readonly save: (_invoice: Invoice) => Effect.Effect<void, RepositoryError>; /** * Find an invoice by order ID. * @param orderId The order ID to search for * @returns Effect that resolves to Option containing the invoice if found * @since 0.1.0 * @example * const result = await invoiceRepository.findByOrderId('order-123') */ readonly findByOrderId: (_orderId: string) => Effect.Effect<Option.Option<Invoice>, RepositoryError>; /** * Find an invoice by invoice number. * @param invoiceNumber The invoice number to search for * @returns Effect that resolves to Option containing the invoice if found * @since 0.1.0 * @example * const result = await invoiceRepository.findByInvoiceNumber('INV-2025-001') */ readonly findByInvoiceNumber: (_invoiceNumber: string) => Effect.Effect<Option.Option<Invoice>, RepositoryError>; /** * List invoices with filtering and pagination. * @param filters Filters to apply to the query * @param pagination Pagination parameters * @returns Effect that resolves to paginated invoices result * @since 0.1.0 * @example * const result = await invoiceRepository.list({ createdBy: 'user' }, { page: 1, limit: 10 }) */ readonly list: (_filters: InvoiceFilters, _pagination: Pagination) => Effect.Effect<PaginatedInvoices, RepositoryError>; } declare const InvoiceRepository_base: Context.TagClass<InvoiceRepository, "@/applayer/ports/InvoiceRepository", InvoiceRepositorySchema>; /** * Context tag for InvoiceRepository service. * Used for dependency injection. * @since 0.1.0 * @see {@link InvoiceRepository} */ declare class InvoiceRepository extends InvoiceRepository_base { } /** * Repository interface for Order operations. * This port defines the contract for order persistence operations. * * @interface OrderRepository * @since 0.1.0 * @see {@link RepositoryError} * @see {@link Order} * @example * import { OrderRepository } from '@invoiceddd/application'; * // Inject implementation at runtime */ interface OrderRepositorySchema { /** * Find an order by ID. * @param orderId The order ID to search for * @returns Effect that resolves to Option containing the order if found * @since 0.1.0 * @example * const result = await orderRepository.findById('order-123') */ readonly findById: (_orderId: string) => Effect.Effect<Option.Option<Order>, RepositoryError>; } declare const OrderRepository_base: Context.TagClass<OrderRepository, "@/applayer/ports/OrderRepository", OrderRepositorySchema>; /** * Context tag for OrderRepository service. * Used for dependency injection. * @since 0.1.0 * @see {@link OrderRepository} */ declare class OrderRepository extends OrderRepository_base { } /** * Repository interface for invoice number operations. * This port defines the contract for invoice number persistence operations. * * @interface InvoiceNumberRepository * @since 0.1.0 * @see {@link RepositoryError} * @example * import { InvoiceNumberRepository } from '@invoiceddd/application'; * // Inject implementation at runtime */ interface InvoiceNumberRepositorySchema { /** * Check if an invoice number already exists in the system. * @param invoiceNumber The invoice number to check * @returns Effect that resolves to true if exists, false otherwise * @since 0.1.0 * @example * const exists = await invoiceNumberRepository.existsByInvoiceNumber('INV-2025-001') */ readonly existsByInvoiceNumber: (_invoiceNumber: string) => Effect.Effect<boolean, RepositoryError>; } declare const InvoiceNumberRepository_base: Context.TagClass<InvoiceNumberRepository, "@/applayer/ports/InvoiceNumberRepository", InvoiceNumberRepositorySchema>; /** * Context tag for InvoiceNumberRepository service. * Used for dependency injection. * @since 0.1.0 * @see {@link InvoiceNumberRepository} */ /** * Context tag for InvoiceNumberRepository service. * Used for dependency injection. * @since 0.1.0 * @see {@link InvoiceNumberRepository} */ declare class InvoiceNumberRepository extends InvoiceNumberRepository_base { } declare const EventBusError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/EventBus/EventBusError"; } & Readonly<A>; /** * Event bus errors * @since 0.1.3 */ declare class EventBusError extends EventBusError_base<{ readonly cause?: unknown; readonly message: string; readonly eventType?: string; }> { } /** * Event handler function type for domain events. * @template T - The domain event type * @since 0.1.3 * @example * const handler: EventHandler<InvoiceCreated> = (event) => * Effect.log(`Invoice created: ${event.invoiceNumber}`) */ type EventHandler<T extends AllDomainEvents> = (event: T) => Effect.Effect<void, never>; /** * Event subscription for a specific event type. * Represents an active subscription to events of a particular type. * @since 0.1.3 */ interface EventSubscription { readonly eventType: string; readonly handler: EventHandler<AllDomainEvents>; readonly subscriptionId: string; } /** * Event bus interface for publishing domain events and managing subscriptions. * * Provides type-safe event publishing and subscription capabilities for domain events. * Supports concurrent event processing and graceful error handling. * * @interface IEventBus * @since 0.1.3 * @see {@link EventBusLive} for default implementation * @example * ```typescript * import { EventBus } from '@invoiceddd/application'; * * const eventBus = yield* EventBus; * await eventBus.start(); * * // Subscribe to events * const subscriptionId = await eventBus.subscribe( * 'InvoiceCreated', * (event) => Effect.log(`Received: ${event.invoiceNumber}`) * ); * * // Publish an event * await eventBus.publish(invoiceCreatedEvent); * ``` */ interface IEventBus { /** * Publish a domain event to all subscribers. * @template E - The domain event type * @param event - The domain event to publish * @returns Effect that completes when event is queued for processing * @since 0.1.3 * @example * await eventBus.publish(invoiceCreatedEvent) */ readonly publish: <E extends AllDomainEvents>(event: E) => Effect.Effect<void, EventBusError>; /** * Subscribe to events of a specific type. * @template E - The domain event type to subscribe to * @param eventType - The event type string to subscribe to * @param handler - The handler function to process events * @returns Effect that resolves to subscription ID for later unsubscribing * @since 0.1.3 * @example * const subscriptionId = await eventBus.subscribe( * 'InvoiceCreated', * (event) => Effect.log(`Processing: ${event.invoiceNumber}`) * ) */ readonly subscribe: <E extends AllDomainEvents>(eventType: string, handler: EventHandler<E>) => Effect.Effect<string, EventBusError>; /** * Unsubscribe from events using subscription ID. * @param subscriptionId - The subscription ID returned from subscribe() * @returns Effect that completes when unsubscribed * @since 0.1.3 * @example * await eventBus.unsubscribe(subscriptionId) */ readonly unsubscribe: (subscriptionId: string) => Effect.Effect<void, EventBusError>; /** * Start the event processing loop. * Must be called before publishing or subscribing to events. * @returns Effect that completes when event processing starts * @since 0.1.3 * @example * await eventBus.start() */ readonly start: Effect.Effect<void, EventBusError>; /** * Stop the event processing and cleanup. * Gracefully shuts down the event bus and clears all subscriptions. * @returns Effect that completes when shutdown is complete * @since 0.1.3 * @example * await eventBus.stop() */ readonly stop: Effect.Effect<void, EventBusError>; } /** * Context tag for EventBus service. * Used for dependency injection in Effect-TS. * @since 0.1.3 * @see {@link IEventBus} */ declare const EventBus: Context.Tag<IEventBus, IEventBus>; /** * Default implementation of EventBus using Effect.Queue for in-memory event processing. * * This implementation provides: * - Type-safe event publishing and subscription * - Automatic event routing to interested subscribers * - Concurrent event processing with error isolation * - Graceful startup and shutdown * - Fire-and-forget event publishing semantics * * @since 0.1.3 * @see {@link IEventBus} * @example * ```typescript * import { EventBusLive } from '@invoiceddd/application'; * * // Use in Effect layer composition * const AppLayer = Layer.mergeAll( * EventBusLive, * // ... other layers * ); * ``` */ declare const EventBusLive: Layer.Layer<IEventBus, never, never>; declare const EventPublishError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/EventPublisher/EventPublishError"; } & Readonly<A>; /** * Event publisher errors. * @since 0.1.3 */ declare class EventPublishError extends EventPublishError_base<{ readonly cause?: unknown; readonly message: string; readonly eventType?: string; }> { } /** * Event publisher interface for publishing domain events. * * Provides a simplified interface for publishing domain events without * needing to manage event bus subscriptions or lifecycle directly. * * @interface EventPublisherSchema * @since 0.1.3 * @see {@link EventPublisherLive} for default implementation * @example * ```typescript * import { EventPublisher } from '@invoiceddd/application'; * * const eventPublisher = yield* EventPublisher; * await eventPublisher.publish(invoiceCreatedEvent); * ``` */ interface EventPublisherSchema { /** * Publish a domain event. * @template T - The event type with a `type` property * @param event - The domain event to publish * @returns Effect that never fails (fire-and-forget semantics) * @since 0.1.3 * @example * await eventPublisher.publish({ * type: 'InvoiceCreated', * invoiceId: '123' * }) */ readonly publish: <T extends { type: string; }>(event: T) => Effect.Effect<void, never>; } /** * Context tag for EventPublisher service. * Used for dependency injection in Effect-TS. * @since 0.1.3 * @see {@link EventPublisherSchema} */ declare const EventPublisher: Context.Tag<EventPublisherSchema, EventPublisherSchema>; /** * Default EventPublisher implementation that uses the EventBus to publish events. * * This implementation ensures that all subscribers receive the events properly * and provides fire-and-forget semantics (never fails, logs errors instead). * * @since 0.1.3 * @see {@link EventPublisherSchema} * @see {@link EventBus} * @example * ```typescript * import { EventPublisherLive, EventBusLive } from '@invoiceddd/application'; * * const AppLayer = Layer.mergeAll( * EventBusLive, * EventPublisherLive, * // ... other layers * ); * ``` */ declare const EventPublisherLive: Layer.Layer<EventPublisherSchema, never, IEventBus>; declare const InvoiceNumberGenerationError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/InvoiceNumberGenerationError"; } & Readonly<A>; /** * Domain error for invoice number generation failures */ declare class InvoiceNumberGenerationError extends InvoiceNumberGenerationError_base<{ readonly cause?: unknown; readonly message: string; }> { } /** * Domain service for generating unique invoice numbers. * This service generates incremental invoice numbers following the pattern INV-XXXX. * * This requires I/O to check existing numbers and thus must not be used within the Domain. * Use it in the application layer. */ interface InvoiceNumberGeneratorSchema { /** * Generates a new unique invoice number following incremental pattern * * @returns Effect that resolves to a unique invoice number or fails with generation error */ readonly generate: () => Effect.Effect<string, InvoiceNumberGenerationError | RepositoryError>; } /** * Context tag for InvoiceNumberGenerator service */ declare const InvoiceNumberGenerator: Context.Tag<InvoiceNumberGeneratorSchema, InvoiceNumberGeneratorSchema>; /** * Context tag for InvoiceConfig */ declare const InvoiceConfigTag: Context.Tag<InvoiceConfig, InvoiceConfig>; /** * Implementation of InvoiceNumberGenerator service */ declare const InvoiceNumberGeneratorLive: Layer.Layer<InvoiceNumberGeneratorSchema, never, InvoiceNumberRepository | InvoiceConfig>; declare const InvoiceNumberConflictError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/InvoiceNumberConflictError"; } & Readonly<A>; declare class InvoiceNumberConflictError extends InvoiceNumberConflictError_base<{ readonly cause?: unknown; readonly message: string; readonly affectedInvoiceNumber: string; }> { } /** * Domain service for validating invoice numbers are unique. * This requires I/O and thus must not be used within the Domain. * * Use it like this: * - In the application layer, get the Repository implementation * - Provide it this service * - Call it and use the result. */ interface InvoiceNumberUniqueCheckerSchema { /** * Validates invoice number uniqueness * * @param invoiceNumber - The invoice number to validate * @returns Effect that succeeds if valid (true), fails with appropriate error if invalid */ readonly validate: (invoiceNumber: string) => Effect.Effect<true, InvoiceNumberConflictError | RepositoryError>; } /** * Context tag for InvoiceNumberUniqueChecker service */ declare const InvoiceNumberUniqueChecker: Context.Tag<InvoiceNumberUniqueCheckerSchema, InvoiceNumberUniqueCheckerSchema>; /** * Implementation of InvoiceNumberUniqueChecker service */ declare const InvoiceNumberUniqueCheckerLive: Layer.Layer<InvoiceNumberUniqueCheckerSchema, never, InvoiceNumberRepository>; declare const InvoiceCreationError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/CreateInvoiceUseCase/InvoiceCreationError"; } & Readonly<A>; /** * Use case errors */ declare class InvoiceCreationError extends InvoiceCreationError_base<{ readonly cause?: unknown; readonly message: string; readonly orderId?: string; readonly invoiceNumber?: string; }> { } declare const PDFGenerationFailedError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/CreateInvoiceUseCase/PDFGenerationFailedError"; } & Readonly<A>; declare class PDFGenerationFailedError extends PDFGenerationFailedError_base<{ readonly cause?: unknown; readonly message: string; readonly invoiceId: string; readonly invoiceNumber: string; }> { } /** * Input for creating an invoice */ interface CreateInvoiceInput { readonly orderId: string; readonly invoiceNumber?: string | undefined; readonly customerSnapshot: CustomerInfo; readonly itemsSnapshot: readonly OrderItem[]; readonly financials: InvoiceFinancials; readonly createdBy: string; readonly pdfRenderOptions?: { readonly legalInfo?: Record<string, unknown>; readonly customOptions?: Record<string, unknown>; }; } /** * Output from creating an invoice */ interface CreateInvoiceOutput { readonly invoice: InvoiceAggregate; readonly pdfBytes: Uint8Array; readonly invoiceCreatedEvent: InvoiceCreated; } /** * Use case for creating and finalizing invoices. * This use case handles the complete invoice creation workflow including: * - Invoice number validation/generation * - Business rule validation * - PDF generation * - Persistence * - Event publishing */ interface ICreateInvoiceUseCase { /** * Create and finalize an invoice * @param input - Invoice creation data * @returns Effect containing created invoice and PDF or error */ readonly execute: (input: CreateInvoiceInput) => Effect.Effect<CreateInvoiceOutput, InvoiceCreationError | InvoiceValidationError | InvoiceNumberFormatError | InvoiceNumberConflictError$1 | InvoiceNumberGenerationError | PDFGenerationFailedError | RepositoryError>; } declare const CreateInvoiceUseCase_base: Context.TagClass<CreateInvoiceUseCase, "@/UseCases/CreateInvoiceUseCase", ICreateInvoiceUseCase>; /** * Context tag for CreateInvoiceUseCase */ declare class CreateInvoiceUseCase extends CreateInvoiceUseCase_base { } /** * Implementation of CreateInvoiceUseCase */ declare const CreateInvoiceUseCaseLive: Layer.Layer<CreateInvoiceUseCase, never, InvoiceRepository | EventPublisherSchema | InvoiceNumberGeneratorSchema | InvoiceNumberUniqueCheckerSchema | InvoiceNumberFormatValidator | PDFRenderer | FinancialCalculationService | ShippingPolicy>; declare const OrderNotFoundError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/OrderNotFoundError"; } & Readonly<A>; /** * Use case errors */ declare class OrderNotFoundError extends OrderNotFoundError_base<{ readonly cause?: unknown; readonly message: string; readonly orderId: string; }> { } declare const InvoiceDraftCreationError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/InvoiceDraftCreationError"; } & Readonly<A>; declare class InvoiceDraftCreationError extends InvoiceDraftCreationError_base<{ readonly cause?: unknown; readonly message: string; readonly orderId: string; }> { } /** * Invoice draft data structure containing all information needed to create an invoice */ interface InvoiceDraft { readonly orderId: string; readonly customerSnapshot: CustomerInfo; readonly itemsSnapshot: readonly OrderItem[]; readonly financials: InvoiceFinancials; readonly requestedBy: string; readonly requestedAt: Date; } /** * Input for requesting an invoice draft */ interface RequestInvoiceInput { readonly orderId: string; readonly requestedBy: string; } /** * Use case for requesting an invoice draft from an existing order. * This use case validates that the order exists and transforms order data * into an editable invoice draft format. */ interface RequestInvoiceUseCaseSchema { /** * Request an invoice draft from an order * @param input - Order ID and user information * @returns Effect containing invoice draft or error */ readonly execute: (input: RequestInvoiceInput) => Effect.Effect<InvoiceDraft, OrderNotFoundError | InvoiceDraftCreationError | RepositoryError>; } declare const RequestInvoiceUseCase_base: Context.TagClass<RequestInvoiceUseCase, "@/UseCases/RequestInvoiceUseCase", RequestInvoiceUseCaseSchema>; /** * Context tag for RequestInvoiceUseCase */ declare class RequestInvoiceUseCase extends RequestInvoiceUseCase_base { } /** * Implementation of RequestInvoiceUseCase */ declare const RequestInvoiceUseCaseLive: Layer.Layer<RequestInvoiceUseCase, never, OrderRepository | EventPublisherSchema>; declare const GetInvoiceError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/GetInvoiceUseCase/GetInvoiceError"; } & Readonly<A>; /** * Use case errors */ declare class GetInvoiceError extends GetInvoiceError_base<{ readonly cause?: unknown; readonly message: string; readonly searchCriteria?: string; }> { } declare const InvoiceNotFoundError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/GetInvoiceUseCase/InvoiceNotFoundError"; } & Readonly<A>; declare class InvoiceNotFoundError extends InvoiceNotFoundError_base<{ readonly cause?: unknown; readonly message: string; readonly searchValue: string; readonly searchType: "orderId" | "invoiceNumber"; }> { } declare const InvalidSearchCriteriaError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/GetInvoiceUseCase/InvalidSearchCriteriaError"; } & Readonly<A>; declare class InvalidSearchCriteriaError extends InvalidSearchCriteriaError_base<{ readonly cause?: unknown; readonly message: string; readonly providedCriteria?: string; }> { } /** * Input for getting an invoice */ interface GetInvoiceInput { readonly orderId?: string; readonly invoiceNumber?: string; readonly returnType?: "json" | "pdf"; } /** * Output from getting an invoice */ interface GetInvoiceOutput { readonly invoice: InvoiceAggregate; readonly pdfBytes?: Uint8Array; } /** * Use case for retrieving a single invoice by various criteria. * This use case supports lookup by orderId or invoiceNumber and can * return either the domain object or PDF bytes based on request. */ interface GetInvoiceUseCaseSchema { /** * Get an invoice by orderId or invoiceNumber * @param input - Search criteria and return type preferences * @returns Effect containing invoice data or error */ readonly execute: (input: GetInvoiceInput) => Effect.Effect<GetInvoiceOutput, GetInvoiceError | InvoiceNotFoundError | InvalidSearchCriteriaError | RepositoryError>; } declare const GetInvoiceUseCase_base: Context.TagClass<GetInvoiceUseCase, "@/UseCases/GetInvoiceUseCase", GetInvoiceUseCaseSchema>; /** * Context tag for GetInvoiceUseCase */ declare class GetInvoiceUseCase extends GetInvoiceUseCase_base { } /** * Implementation of GetInvoiceUseCase */ declare const GetInvoiceUseCaseLive: Layer.Layer<GetInvoiceUseCase, never, InvoiceRepository | InvoiceNumberFormatValidator>; declare const ListInvoicesError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/ListInvoicesUseCase/ListInvoicesError"; } & Readonly<A>; /** * Use case errors */ declare class ListInvoicesError extends ListInvoicesError_base<{ readonly cause?: unknown; readonly message: string; }> { } declare const InvalidPaginationError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/ListInvoicesUseCase/InvalidPaginationError"; } & Readonly<A>; declare class InvalidPaginationError extends InvalidPaginationError_base<{ readonly cause?: unknown; readonly message: string; readonly page?: number; readonly limit?: number; }> { } declare const InvalidFiltersError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & { readonly _tag: "@/ListInvoicesUseCase/InvalidFiltersError"; } & Readonly<A>; declare class InvalidFiltersError extends InvalidFiltersError_base<{ readonly cause?: unknown; readonly message: string; readonly invalidField?: string; }> { } /** * Input for listing invoices */ interface ListInvoicesInput { readonly filters?: { readonly invoiceNumber?: string; readonly dateFrom?: Date; readonly dateTo?: Date; readonly minTotal?: number; readonly maxTotal?: number; readonly createdBy?: string; }; readonly pagination?: { readonly page?: number; readonly limit?: number; }; } /** * Output from listing invoices */ interface ListInvoicesOutput { readonly invoices: readonly InvoiceAggregate[]; readonly totalCount: number; readonly page: number; readonly limit: number; readonly totalPages: number; readonly hasNextPage: boolean; readonly hasPrevPage: boolean; } /** * Use case for querying invoices with filters and pagination. * This use case handles filtering by various criteria and provides * paginated results for efficient data handling. */ interface ListInvoicesUseCaseSchema { /** * List invoices with filtering and pagination * @param input - Filters and pagination parameters * @returns Effect containing paginated invoices or error */ readonly execute: (input: ListInvoicesInput) => Effect.Effect<ListInvoicesOutput, ListInvoicesError | InvalidPaginationError | InvalidFiltersError | RepositoryError>; } declare const ListInvoicesUseCase_base: Context.TagClass<ListInvoicesUseCase, "@/UseCases/ListInvoicesUseCase", ListInvoicesUseCaseSchema>; /** * Context tag for ListInvoicesUseCase */ declare class ListInvoicesUseCase extends ListInvoicesUseCase_base { } /** * Implementation of ListInvoicesUseCase */ declare const ListInvoicesUseCaseLive: Layer.Layer<ListInvoicesUseCase, never, InvoiceRepository | InvoiceNumberFormatValidator>; export { type CreateInvoiceInput, type CreateInvoiceOutput, CreateInvoiceUseCase, CreateInvoiceUseCaseLive, EventBus, EventBusError, EventBusLive, type EventHandler, EventPublishError, EventPublisher, EventPublisherLive, type EventPublisherSchema, type EventSubscription, GetInvoiceError, type GetInvoiceInput, type GetInvoiceOutput, GetInvoiceUseCase, GetInvoiceUseCaseLive, type GetInvoiceUseCaseSchema, type ICreateInvoiceUseCase, type IEventBus, InvalidFiltersError, InvalidPaginationError, InvalidSearchCriteriaError, InvoiceConfigTag, InvoiceCreationError, type InvoiceDraft, InvoiceDraftCreationError, type InvoiceFilters, InvoiceNotFoundError, InvoiceNumberConflictError, InvoiceNumberGenerationError, InvoiceNumberGenerator, InvoiceNumberGeneratorLive, type InvoiceNumberGeneratorSchema, InvoiceNumberRepository, type InvoiceNumberRepositorySchema, InvoiceNumberUniqueChecker, InvoiceNumberUniqueCheckerLive, type InvoiceNumberUniqueCheckerSchema, InvoiceRepository, type InvoiceRepositorySchema, ListInvoicesError, type ListInvoicesInput, type ListInvoicesOutput, ListInvoicesUseCase, ListInvoicesUseCaseLive, type ListInvoicesUseCaseSchema, OrderNotFoundError, OrderRepository, type OrderRepositorySchema, PDFGenerationFailedError, type PaginatedInvoices, type Pagination, type RequestInvoiceInput, RequestInvoiceUseCase, RequestInvoiceUseCaseLive, type RequestInvoiceUseCaseSchema };