import { type EventPublishOptions } from "../events/index.js";
import type { DomainEventDef, EventBusPort, InferEventPayload } from "./events.js";
type MaybePromise<T> = T | Promise<T>;
/**
 * Work function executed inside a Unit of Work.
 *
 * `tx` contains transaction-scoped app ports, usually repositories plus
 * side-effect recorders such as `events`, `jobs`, or `audit`.
 */
export type UnitOfWorkCallback<TxPorts, Result> = (tx: TxPorts) => MaybePromise<Result>;
/**
 * A transaction boundary for application workflows.
 *
 * The transaction ports are app-owned. A database adapter can provide
 * transaction-scoped repositories, while test or in-memory adapters can use
 * `createNoopUnitOfWork`.
 */
export interface UnitOfWorkPort<TxPorts> {
    /**
     * Run application work with transaction-scoped ports.
     *
     * Durable implementations should commit only if this callback resolves.
     */
    transaction<Result>(work: UnitOfWorkCallback<TxPorts, Result>): Promise<Result>;
}
/**
 * Hooks for `createNoopUnitOfWork(...)`.
 */
export interface NoopUnitOfWorkOptions<TxPorts> {
    /**
     * Runs after the callback completes successfully.
     *
     * Use this to flush buffered domain events after the work has committed.
     */
    afterCommit?: (tx: TxPorts) => MaybePromise<void>;
    /**
     * Runs after the callback throws.
     *
     * Use this to clear buffers or release test resources. The original error is
     * rethrown after this hook runs.
     */
    afterRollback?: (error: unknown, tx: TxPorts) => MaybePromise<void>;
}
/**
 * Best-effort observers for `createObservedUnitOfWork(...)`.
 */
export interface ObservedUnitOfWorkOptions {
    /**
     * Runs after the wrapped Unit of Work resolves successfully.
     *
     * Observer failures are isolated and never reject the committed operation.
     */
    afterCommit: () => MaybePromise<void>;
    /**
     * Receives an `afterCommit` failure. Failures from this observer are also
     * isolated.
     */
    onObserverError?: (error: unknown) => MaybePromise<void>;
}
/**
 * Domain event captured by a buffered event recorder.
 */
export interface RecordedDomainEvent {
    /**
     * Event definition used to validate the payload before publishing.
     */
    event: DomainEventDef;
    /**
     * Stable event name.
     */
    eventName: string;
    /**
     * Unparsed payload recorded during the transaction.
     */
    payload: unknown;
    /** Optional metadata propagated when the event is flushed. */
    options?: EventPublishOptions;
}
/**
 * Transaction-scoped port used to record domain events.
 *
 * Use cases record events here during the Unit of Work. The adapter decides
 * whether to publish after commit, enqueue through an outbox, or buffer for a
 * test assertion.
 */
export interface DomainEventRecorderPort {
    /**
     * Record a domain event payload.
     */
    record<E extends DomainEventDef>(event: E, payload: InferEventPayload<E>, options?: EventPublishOptions): Promise<void> | void;
}
/**
 * In-memory event recorder that can be inspected, cleared, or flushed.
 */
export interface BufferedDomainEventRecorder extends DomainEventRecorderPort {
    /**
     * Return recorded events without clearing them.
     */
    entries(): readonly RecordedDomainEvent[];
    /**
     * Remove all recorded events.
     */
    clear(): void;
    /**
     * Validate and publish all recorded events to an event bus in FIFO order.
     */
    flush(eventBus: EventBusPort): Promise<void>;
}
/**
 * Create a simple Unit of Work implementation for tests, in-memory adapters,
 * and infrastructure that already handles transactions elsewhere.
 *
 * This helper does not create database transactions. It gives applications the
 * same UOW shape everywhere and runs commit/rollback hooks around the callback.
 *
 * @param txPortsOrFactory - Transaction-scoped ports or a factory that creates
 * them per transaction call.
 * @param options - Optional commit and rollback hooks.
 * @returns A Unit of Work port with no durable transaction semantics.
 */
export declare function createNoopUnitOfWork<TxPorts>(txPortsOrFactory: TxPorts | (() => TxPorts), options?: NoopUnitOfWorkOptions<TxPorts>): UnitOfWorkPort<TxPorts>;
/**
 * Decorate a Unit of Work with an isolated post-commit observer.
 *
 * The observer runs only after the wrapped transaction resolves. Its failure
 * cannot turn a committed operation into an apparent transaction failure.
 * Use the observer to schedule best-effort follow-up work; durable side
 * effects still belong inside the transaction through an outbox.
 */
export declare function createObservedUnitOfWork<TxPorts>(options: {
    unitOfWork: UnitOfWorkPort<TxPorts>;
} & ObservedUnitOfWorkOptions): UnitOfWorkPort<TxPorts>;
/**
 * Create a recorder that buffers domain events until the caller flushes them.
 *
 * Unit of Work adapters commonly flush this recorder from an `afterCommit`
 * hook so events are not published when the work rolls back.
 *
 * @returns A buffered domain event recorder for tests or Unit of Work adapters.
 */
export declare function createDomainEventRecorder(): BufferedDomainEventRecorder;
export {};
//# sourceMappingURL=unit-of-work.d.ts.map