import { Request } from "./context.js";

//#region src/hooks.d.ts

/**
 * Interceptors wrap handler and ctx.run() execution. They are part of the
 * invocation — anything that happens inside them (including after `next()`)
 * affects the invocation outcome.
 *
 * ## Error behavior
 *
 * Errors thrown at any point (before or after `next()`) affect the invocation:
 *
 * - **{@link TerminalError}** — the invocation **fails immediately**, no retry.
 * - **Any other error** — Restate **retries** the invocation.
 * - On suspension or pause, `next()` also rejects with an error. This does not
 *   mean the invocation failed — the attempt is simply ending. Do any cleanup
 *   you need and rethrow.
 *
 * ## Output
 *
 * Interceptors **cannot alter the handler's success return value** (the `void`
 * signature means there is no way to replace it), but they **can transform
 * errors** by catching and rethrowing a different error.
 *
 * ## Rules
 *
 * - `next()` must be called exactly once.
 *
 * ## When interceptors fire
 *
 * - `handler` fires on every attempt.
 * - `run` fires when the `ctx.run()` closure executes. If the result is
 *   already in the journal, the closure is skipped and so is the interceptor.
 *
 * @example
 * ```ts
 * interceptor: {
 *   handler: async (next) => {
 *     console.log(`before ${ctx.request.target}`);
 *     try {
 *       await next();
 *       console.log(`after ${ctx.request.target}`);
 *     } catch (e) {
 *       console.log(`error ${ctx.request.target}: ${e}`);
 *       // Always rethrow — swallowing the error changes the
 *       // invocation outcome. You can also throw a different
 *       // error (e.g. TerminalError to fail immediately).
 *       throw e;
 *     }
 *   },
 *   run: async (name, next) => {
 *     console.log(`  before run "${name}"`);
 *     try {
 *       await next();
 *       console.log(`  after run "${name}"`);
 *     } catch (e) {
 *       console.log(`  error run "${name}": ${e}`);
 *       throw e;
 *     }
 *   },
 * }
 * ```
 */
interface Interceptor {
  /** Wraps the entire handler invocation. Fires on every attempt. */
  handler?: (next: () => Promise<void>) => Promise<void>;
  /**
   * Wraps each `ctx.run()` call. Only fires for runs that actually execute —
   * replayed runs (already in the journal) are skipped.
   * `name` is the run's label.
   */
  run?: (name: string, next: () => Promise<void>) => Promise<void>;
}
interface Hooks {
  interceptor?: Interceptor;
}
/**
 * Factory called on every attempt. Receives the invocation request,
 * returns hooks for that attempt's lifetime. Each attempt gets a fresh call.
 */
type HooksProvider = (ctx: {
  request: Request;
}) => Hooks;
//#endregion
export { Hooks, HooksProvider, Interceptor };
//# sourceMappingURL=hooks.d.ts.map