{"version":3,"file":"index.mjs","sources":["../src/hooks/useMongoSession.ts","../src/hooks/onMongoSessionCommitted.ts","../src/hooks/scope.ts","../src/scope.ts","../src/hooks/useTransactionEffect.ts","../src/hooks/onCommitted.ts","../src/hooks/onRollback.ts","../src/utils.ts","../src/withMongoTransaction.ts","../src/withTransaction.ts","../src/withTransactionControlled.ts"],"sourcesContent":["import { createContext, hasInjectionContext } from '@andrew_l/context';\nimport type { ClientSession } from 'mongodb';\n\nexport const [injectMongoSession, provideMongoSession] =\n  createContext<ClientSession>('withMongoTransaction');\n\n/**\n * Returns the current transaction session if executed within `withMongoTransaction()` otherwise returns `null`\n *\n * @example\n * async function createAlert() {\n *   const session = useMongoSession();\n *\n *   await db.alerts.insertOne(\n *     { title: 'Order Created' },\n *     { session: session ?? undefined }\n *   );\n * }\n *\n * @group Hooks\n */\nexport function useMongoSession(): ClientSession | null {\n  return hasInjectionContext() ? injectMongoSession(null) : null;\n}\n","import {\n  type AnyFunction,\n  type Awaitable,\n  defer,\n  isPromise,\n} from '@andrew_l/toolkit';\nimport type { ClientSession } from 'mongodb';\nimport { injectMongoSession } from './useMongoSession';\n\nexport type OnMongoSessionCommittedResult<T> = {\n  /**\n   * Executes the provided function upon transaction commit.\n   *\n   * Returns `T` if the transaction is committed and the function completes successfully.\n   *\n   * Returns `undefined` if the transaction is explicitly aborted or ends without committing.\n   *\n   * Rejects if the function throws an error.\n   */\n  promise: Promise<T | undefined>;\n\n  cancel: () => void;\n};\n\n/**\n * Executes the provided function upon transaction commit.\n *\n * Returns `T` if the transaction is committed and the function completes successfully.\n *\n * Returns `false` if the transaction ends without committing.\n *\n * Rejects if the function throws an error.\n *\n * @example\n * const { promise } = onTransactionCommitted(async () => {\n *   console.info('Transaction committed successfully!');\n *   return Math.random(); // Random value generated after commit\n * });\n *\n * promise.then(result => {\n *   if (result !== false) {\n *     console.info('Handler result:', result); // e.g., Handler result: 0.07576196837476501\n *   }\n * });\n *\n * @group Hooks\n */\nexport function onMongoSessionCommitted<T>(\n  fn: () => Awaitable<T>,\n): OnMongoSessionCommittedResult<T>;\n\nexport function onMongoSessionCommitted<T>(\n  session: ClientSession,\n  fn: () => Awaitable<T>,\n): OnMongoSessionCommittedResult<T>;\n\nexport function onMongoSessionCommitted(\n  ...args: any[]\n): OnMongoSessionCommittedResult<unknown> {\n  let session: ClientSession;\n  let fn: AnyFunction;\n\n  if (args.length === 2) {\n    [session, fn] = args;\n  } else {\n    session = injectMongoSession();\n    fn = args[0];\n  }\n\n  const q = defer<undefined | unknown>();\n\n  const onEnded = () => {\n    if (!session.transaction.isCommitted) {\n      return q.resolve(undefined);\n    }\n\n    try {\n      const result = fn();\n\n      if (isPromise(result)) {\n        result.then(r => q.resolve(r)).catch(q.reject);\n      } else {\n        q.resolve(result);\n      }\n    } catch (err) {\n      q.reject(err);\n    }\n  };\n\n  session.once('ended', onEnded);\n\n  const cancel = () => {\n    session.off('ended', onEnded);\n  };\n\n  return {\n    promise: q.promise,\n    cancel,\n  };\n}\n","import { createContext } from '@andrew_l/context';\nimport type { TransactionScope } from '../scope';\n\nexport const [injectTransactionScope, provideTransactionScope] =\n  createContext<TransactionScope>([\n    'withTransaction',\n    'withTransactionControlled',\n    'withMongoTransaction',\n  ]);\n","import { withContext } from '@andrew_l/context';\nimport {\n  type Awaitable,\n  assert,\n  asyncForEach,\n  catchError,\n  env,\n  isFunction,\n  logger,\n  noop,\n} from '@andrew_l/toolkit';\nimport { provideTransactionScope } from './hooks/scope';\n\nexport interface TransactionEffect {\n  /**\n   * Specifies when the transaction effect should run:\n   *\n   * `pre` -  execute immediately\n   *\n   *  `post` - execute before transaction commit\n   *\n   * @default: \"pre\"\n   */\n  flush: 'pre' | 'post';\n\n  /**\n   * Setup effect function. You can return a cleanup callback to be used as a rollback.\n   */\n  setup: EffectCallback;\n\n  /**\n   * Cleanup function.\n   */\n  cleanup?: EffectCleanup;\n\n  /**\n   * Useful for debugging execution logs.\n   */\n  name?: string;\n\n  dependencies?: readonly any[];\n}\n\nexport type EffectCallback = () => Awaitable<EffectCleanup | void>;\n\nexport type EffectCleanup = () => Awaitable<void>;\n\nexport interface TransactionOnCommitted {\n  callback: OnCommittedCallback;\n  dependencies?: readonly any[];\n}\n\nexport type OnCommittedCallback = () => Awaitable<void>;\n\nexport interface TransactionOnRollback {\n  callback: OnRollbackCallback;\n  dependencies?: readonly any[];\n}\n\nexport type OnRollbackCallback = () => Awaitable<void>;\n\ninterface TransactionScopeHooks {\n  effects: {\n    cursor: number;\n    byCursor: TransactionEffect[];\n  };\n  committed: {\n    cursor: number;\n    byCursor: TransactionOnCommitted[];\n  };\n  rollbacks: {\n    cursor: number;\n    byCursor: TransactionOnRollback[];\n  };\n}\n\nexport class TransactionScope<T = any, Args extends any[] = any[]> {\n  /**\n   * @internal\n   */\n  log = logger('TransactionScope');\n\n  /**\n   * @internal\n   * Indicates currently ran scope\n   */\n  _active: boolean = false;\n\n  /**\n   * Last run error\n   */\n  error: Error | undefined;\n\n  /**\n   * Last run result\n   */\n  result: T | undefined;\n\n  run: (this: any, ...args: Args) => Promise<void>;\n\n  /**\n   * @internal\n   */\n  hooks: TransactionScopeHooks = {\n    committed: { byCursor: [], cursor: 0 },\n    effects: { byCursor: [], cursor: 0 },\n    rollbacks: { byCursor: [], cursor: 0 },\n  };\n\n  constructor(private fn: (...args: Args) => T) {\n    const scope = this;\n\n    this.run = function (...args) {\n      const self = this === scope ? undefined : this;\n      return scope._run(self, ...args);\n    };\n  }\n\n  get active(): boolean {\n    return this._active;\n  }\n\n  /**\n   * @internal\n   */\n  async _run(self?: any, ...args: Args): Promise<void> {\n    assert.ok(!this._active, 'Cannot run while transaction active.');\n\n    this.reset();\n    this._active = true;\n\n    const [cbError, cbResult] = await withContext(() => {\n      provideTransactionScope(this);\n      return catchError(this.fn.bind(self, ...(args as any[])));\n    })();\n\n    if (cbError) {\n      this.error = cbError;\n    } else {\n      const applyError = await effectsApply(this, 'post');\n\n      if (applyError) {\n        this.error = applyError;\n      }\n\n      this.result = cbResult;\n    }\n\n    this._active = false;\n  }\n\n  async commit(): Promise<void> {\n    assert.ok(!this._active, 'Cannot commit while transaction active.');\n    assert.ok(!this.error, this.error);\n\n    await asyncForEach(\n      this.hooks.committed.byCursor,\n      h => catchError(h.callback) as any,\n      { concurrency: 4 },\n    );\n\n    this.reset();\n    this.clean();\n  }\n\n  async rollback(): Promise<void> {\n    assert.ok(!this._active, 'Cannot rollback while transaction active.');\n\n    const error = await effectsCleanup(this);\n\n    if (error) {\n      return Promise.reject(error);\n    }\n\n    await asyncForEach(\n      this.hooks.rollbacks.byCursor,\n      h => catchError(h.callback) as any,\n      { concurrency: 4 },\n    );\n\n    this.reset();\n    this.clean();\n  }\n\n  reset() {\n    assert.ok(!this._active, 'Cannot reset while transaction active.');\n\n    this.hooks.effects.cursor = 0;\n    this.hooks.committed.cursor = 0;\n    this.hooks.rollbacks.cursor = 0;\n    this.result = undefined;\n    this.error = undefined;\n  }\n\n  clean() {\n    assert.ok(!this._active, 'Cannot clean while transaction active.');\n    this.hooks.effects = { byCursor: [], cursor: 0 };\n    this.hooks.committed = { byCursor: [], cursor: 0 };\n    this.hooks.rollbacks = { byCursor: [], cursor: 0 };\n  }\n}\n\nexport function createTransactionScope<T = any, Args extends any[] = any[]>(\n  fn: (...args: Args) => T,\n): TransactionScope<Awaited<T>, Args> {\n  return new TransactionScope<any>(fn);\n}\n\nexport async function effectsApply(\n  scope: TransactionScope,\n  reason: string = 'no reason',\n): Promise<Error | undefined> {\n  let error: Error | undefined;\n\n  const onComplete = (err: Error | undefined) => void (error = err || error);\n\n  await asyncForEach(\n    scope.hooks.effects.byCursor,\n    effect => applyEffect(scope, effect, reason).then(onComplete),\n    {\n      concurrency: 4,\n    },\n  );\n\n  return error;\n}\n\nexport async function effectsCleanup(\n  scope: TransactionScope,\n  reason: string = 'no reason',\n): Promise<Error | undefined> {\n  let error: Error | undefined;\n\n  const onComplete = (err: Error | undefined) => void (error = err || error);\n\n  await asyncForEach(\n    scope.hooks.effects.byCursor,\n    effect => cleanupEffect(scope, effect, reason).then(onComplete),\n    {\n      concurrency: 4,\n    },\n  );\n\n  return error;\n}\n\nexport async function applyEffect(\n  scope: TransactionScope,\n  effect: TransactionEffect,\n  reason: string = 'no reason',\n): Promise<Error | undefined> {\n  if (effect.cleanup) return;\n\n  scope.log.debug(\n    'Effect name = %s, flush = %s, apply by %s',\n    effect.name,\n    effect.flush,\n    reason,\n  );\n\n  const [err, effectResult] = await catchError(effect.setup);\n\n  if (err) {\n    !env.isTest &&\n      scope.log.error(\n        'Effect name = %s, flush = %s apply error',\n        effect.name,\n        effect.flush,\n        err,\n      );\n    return err;\n  }\n\n  effect.cleanup = isFunction(effectResult) ? effectResult : noop;\n\n  return;\n}\n\nexport async function cleanupEffect(\n  scope: TransactionScope,\n  effect: TransactionEffect,\n  reason: string = 'no reason',\n): Promise<Error | undefined> {\n  if (!effect.cleanup) return;\n\n  scope.log.debug(\n    'Effect name = %s, flush = %s, cleanup by %s',\n    effect.name,\n    effect.flush,\n    reason,\n  );\n\n  const [err] = await catchError(effect.cleanup);\n\n  if (err) {\n    !env.isTest &&\n      scope.log.error(\n        'Effect name = %s, flush = %s, cleanup error',\n        effect.name,\n        effect.flush,\n        err,\n      );\n    return err;\n  }\n\n  effect.cleanup = undefined;\n}\n","import { isEqual } from '@andrew_l/toolkit';\nimport {\n  type TransactionEffect,\n  type TransactionScope,\n  applyEffect,\n  cleanupEffect,\n} from '../scope';\nimport { injectTransactionScope } from './scope';\n\nexport type UseTransactionEffectOptions = Partial<\n  Pick<TransactionEffect, 'name' | 'flush' | 'dependencies'>\n>;\n\n/**\n * Executes a transactional effect with cleanup on error or rollback.\n *\n * Ensures the `callback` function is executed only once per transaction, even during retries.\n * On errors or dependency changes, the cleanup logic is invoked before re-execution to maintain consistency.\n *\n * @param setup A function defining the transactional effect. It is guaranteed to run once per transaction\n *              and may be re-executed after cleanup if dependencies change.\n *\n * @example\n * const confirmOrder = withMongoTransaction({\n *   connection: () => mongoose.connection.getClient(),\n *   async fn(session) {\n *     // Register an alert as a transactional effect\n *     await useTransactionEffect(async () => {\n *       const alertId = await alertService.create({\n *         title: `Order Confirmed: ${orderId}`,\n *       });\n *\n *       // Define cleanup logic to remove the alert on rollback\n *       return () => alertService.removeById(alertId);\n *     });\n *\n *     // Simulate order processing (e.g., database updates)\n *     await db\n *       .collection('orders')\n *       .updateOne({ orderId }, { $set: { status: 'confirmed' } }, { session });\n *\n *     // Simulate an error to test rollback\n *     throw new Error('Simulated transaction failure');\n *   },\n * });\n *\n * @group Hooks\n */\nexport async function useTransactionEffect(\n  setup: TransactionEffect['setup'],\n  options: UseTransactionEffectOptions = {},\n): Promise<void> {\n  const scope = injectTransactionScope();\n\n  const { cursor, byCursor } = scope.hooks.effects;\n\n  const effectConfig: Partial<TransactionEffect> = byCursor[cursor] ?? {};\n\n  const flush = options?.flush || 'pre';\n  const name = options?.name || `Effect #${cursor + 1}`;\n  const dependencies = options.dependencies ?? [];\n  const prevDependencies = effectConfig.dependencies;\n\n  byCursor[cursor] = {\n    ...effectConfig,\n    dependencies,\n    flush,\n    name,\n    setup,\n  };\n\n  if (dependencies && prevDependencies) {\n    if (!isEqual(dependencies, prevDependencies)) {\n      scope.log.debug(\n        'Effect name = %s, flush = %s, caused by dependencies',\n        name,\n        flush,\n        {\n          prevDependencies,\n          newDependencies: dependencies,\n        },\n      );\n\n      await scheduleEffect(scope, cursor);\n    }\n  } else {\n    scope.log.debug(\n      'Effect name = %s, flush = %s, caused by missing dependencies',\n      name,\n      flush,\n    );\n\n    await scheduleEffect(scope, cursor);\n  }\n\n  scope.hooks.effects.cursor++;\n}\n\nasync function scheduleEffect(scope: TransactionScope, cursor: number) {\n  const { byCursor } = scope.hooks.effects;\n  const effect = byCursor[cursor]!;\n\n  const cleanupErr = await cleanupEffect(scope, effect, 'schedule pre');\n\n  if (cleanupErr) {\n    return Promise.reject(cleanupErr);\n  }\n\n  if (effect.flush === 'pre') {\n    const err = await applyEffect(scope, effect, 'schedule pre');\n\n    if (err) {\n      return Promise.reject(err);\n    }\n  }\n}\n","import { type Fn, isEqual, noop } from '@andrew_l/toolkit';\nimport type { OnCommittedCallback } from '../scope';\nimport { injectTransactionScope } from './scope';\n\n/**\n * Registers a callback to be executed upon transaction commitment, with support\n * for dependency-based updates.\n *\n * This function is used within a transaction scope to perform specific actions\n * when a transaction is committed. If dependencies are provided, the callback\n * is re-registered only if the dependencies have changed. Otherwise, the\n * callback is registered unconditionally.\n *\n * @param {OnCommittedCallback} callback - The function to be executed upon\n *   transaction commitment.\n * @param {readonly any[]} [dependencies=[]] - An optional array of dependencies\n *   to determine if the callback should be re-registered. If the dependencies\n *   differ from the previously registered ones, the callback is updated.\n * @returns {Fn} A cleanup function to cancel event listener.\n *\n * @example\n * // Basic usage without dependencies\n * onCommitted(() => {\n *   console.log('Transaction committed!');\n * });\n *\n * @example\n * // Using dependencies\n * count++;\n * onCommitted(() => {\n *   console.log(`Commit #${count}`);\n * }, [count]);\n *\n * @example\n * //  Cancel by request\n * const cancel = onCommitted(() => {\n *   console.log('This will run only once!');\n * });\n *\n * if (orderReceived) {\n *   cancel(); // Prevents onCommitted from running\n * }\n *\n * @group Hooks\n */\nexport function onCommitted(\n  callback: OnCommittedCallback,\n  dependencies?: readonly any[],\n): Fn {\n  const scope = injectTransactionScope();\n  const { cursor, byCursor } = scope.hooks.committed;\n\n  const config = byCursor[cursor];\n\n  if (dependencies && config?.dependencies) {\n    if (!isEqual(dependencies, config.dependencies)) {\n      scope.log.debug('OnCommitted caused by dependencies', {\n        prevDependencies: config.dependencies,\n        newDependencies: dependencies,\n        cursor,\n      });\n\n      byCursor[cursor] = { callback, dependencies };\n    }\n  } else {\n    scope.log.debug('OnCommitted caused by missing dependencies', { cursor });\n    byCursor[cursor] = { callback, dependencies };\n  }\n\n  scope.hooks.committed.cursor++;\n\n  return () => {\n    byCursor[cursor].callback = noop;\n  };\n}\n","import { type Fn, isEqual, noop } from '@andrew_l/toolkit';\nimport type { OnRollbackCallback } from '../scope';\nimport { injectTransactionScope } from './scope';\n\n/**\n * Registers a callback to be executed upon transaction rollback, with support\n * for dependency-based updates.\n *\n * This function is used within a transaction scope to perform specific actions\n * when a transaction is rolled back. If dependencies are provided, the callback\n * is re-registered only if the dependencies have changed. Otherwise, the\n * callback is registered unconditionally.\n *\n * @param {OnRollbackCallback} callback - The function to be executed upon\n *   transaction rollback.\n * @param {readonly any[]} [dependencies=[]] - An optional array of dependencies\n *   to determine if the callback should be re-registered. If the dependencies\n *   differ from the previously registered ones, the callback is updated.\n * @returns {Fn} A cleanup function to cancel event listener.\n *\n * @example\n * // Basic usage without dependencies\n * onRollback(() => {\n *   console.log('Transaction rolled back!');\n * });\n *\n * @example\n * // Using dependencies\n * count++;\n * onRollback(() => {\n *   console.log(`Rollback detected, flag is ${flag}`);\n * }, [count]);\n *\n * @example\n * // Cancel by request\n * const cancel = onRollback(() => {\n *   console.log('This will run only once on rollback!');\n * });\n *\n * if (orderReceived) {\n *   cancel(); // Prevents onRollback from running\n * }\n *\n * @group Hooks\n */\nexport function onRollback(\n  callback: OnRollbackCallback,\n  dependencies?: readonly any[],\n): Fn {\n  const scope = injectTransactionScope();\n  const { cursor, byCursor } = scope.hooks.rollbacks;\n\n  const config = byCursor[cursor];\n\n  if (dependencies && config?.dependencies) {\n    if (!isEqual(dependencies, config.dependencies)) {\n      scope.log.debug('OnCommitted caused by dependencies', {\n        prevDependencies: config.dependencies,\n        newDependencies: dependencies,\n        cursor,\n      });\n\n      byCursor[cursor] = { callback, dependencies };\n    }\n  } else {\n    scope.log.debug('OnCommitted caused by missing dependencies', { cursor });\n    byCursor[cursor] = { callback, dependencies };\n  }\n\n  scope.hooks.committed.cursor++;\n\n  return () => {\n    byCursor[cursor].callback = noop;\n  };\n}\n","import { has, isFunction } from '@andrew_l/toolkit';\nimport type { Transaction } from 'mongodb';\nimport type {\n  ClientSessionLike,\n  MongoClientLike,\n} from './withMongoTransaction';\n\nexport function isTransactionAborted(transaction: Transaction): boolean {\n  return (transaction as any)?.state === 'TRANSACTION_ABORTED';\n}\n\nexport function isTransactionCommittedEmpty(transaction: Transaction): boolean {\n  return (transaction as any)?.state === 'TRANSACTION_COMMITTED_EMPTY';\n}\n\nexport function isMongoClientLike(value: unknown): value is MongoClientLike {\n  return has(value, ['startSession']) && isFunction(value.startSession);\n}\n\nexport function isClientSessionLike(\n  value: unknown,\n): value is ClientSessionLike {\n  return (\n    has(value, ['withTransaction', 'endSession']) &&\n    isFunction(value.withTransaction) &&\n    isFunction(value.endSession)\n  );\n}\n","import {\n  type ClientSession,\n  type ClientSessionOptions,\n  MongoTransactionError,\n} from 'mongodb';\n\nimport {\n  type AnyFunction,\n  type Awaitable,\n  catchError,\n  deepDefaults,\n  isFunction,\n  noop,\n} from '@andrew_l/toolkit';\nimport { provideMongoSession } from './hooks/useMongoSession';\nimport { createTransactionScope } from './scope';\nimport {\n  isMongoClientLike,\n  isTransactionAborted,\n  isTransactionCommittedEmpty,\n} from './utils';\n\nconst DEF_SESSION_OPTIONS = Object.freeze({\n  defaultTransactionOptions: {\n    readPreference: 'primary',\n    readConcern: { level: 'local' },\n    writeConcern: { w: 'majority' },\n  },\n} as ClientSessionOptions);\n\nexport interface MongoClientLike {\n  startSession(options: Record<string, any>): ClientSessionLike;\n}\n\nexport interface ClientSessionLike {\n  withTransaction(fn: AnyFunction): Promise<any>;\n  endSession(): Promise<void>;\n}\n\ntype ConnectionValue = MongoClientLike | (() => Awaitable<MongoClientLike>);\n\ntype Callback<T, K = any, Args extends Array<any> = any[]> = (\n  this: K,\n  session: ClientSession,\n  ...args: Args\n) => Awaitable<T>;\n\nexport interface WithMongoTransactionOptions<\n  T,\n  K = any,\n  Args extends Array<any> = any[],\n> {\n  /**\n   * Mongodb connection getter\n   */\n  connection: ConnectionValue;\n\n  /**\n   * Transaction session options\n   *\n   * @default: {\n   *   defaultTransactionOptions: {\n   *     readPreference: 'primary',\n   *     readConcern: { level: 'local' },\n   *     writeConcern: { w: 'majority' },\n   *   }\n   * }\n   */\n  sessionOptions?: ClientSessionOptions;\n\n  /**\n   * Configures a timeoutMS expiry for the entire withTransactionCallback.\n   *\n   * @remarks\n   * - The remaining timeout will not be applied to callback operations that do not use the ClientSession.\n   * - Overriding timeoutMS for operations executed using the explicit session inside the provided callback will result in a client-side error.\n   */\n  timeoutMS?: number;\n\n  /**\n   * Transaction function that will be executed\n   *\n   * ⚠️ Possible several times!\n   */\n  fn: Callback<T, K, Args>;\n}\n\ntype WithMongoTransactionWrapped<\n  T,\n  K = any,\n  Args extends Array<any> = any[],\n> = (this: K, ...args: Args) => Promise<T>;\n\n/**\n * Runs a provided callback within a transaction, retrying either the commitTransaction operation or entire transaction as needed (and when the error permits) to better ensure that the transaction can complete successfully.\n *\n * Passes the session as the function's first argument or via `useMongoSession()` hook\n *\n * @example\n * const executeTransaction = withMongoTransaction({\n *   connection: () => mongoose.connection.getClient(),\n *   async fn() {\n *     const session = useMongoSession();\n *     const orders = mongoose.connection.collection('orders');\n *\n *     const { modifiedCount } = await orders.updateMany(\n *       { status: 'pending' },\n *       { $set: { status: 'confirmed' } },\n *       { session },\n *     );\n *   },\n * });\n *\n * @group Main\n */\nexport function withMongoTransaction<\n  T,\n  K = any,\n  Args extends Array<any> = any[],\n>(\n  options: WithMongoTransactionOptions<T, K, Args>,\n): WithMongoTransactionWrapped<T, K, Args>;\n\n/**\n * Runs a provided callback within a transaction, retrying either the commitTransaction operation or entire transaction as needed (and when the error permits) to better ensure that the transaction can complete successfully.\n *\n * Passes the session as the function's first argument or via `useMongoSession()` hook\n *\n * @example\n * const executeTransaction = withMongoTransaction(mongoose.connection.getClient(), async () => {\n *   const session = useMongoSession();\n *   const orders = mongoose.connection.collection('orders');\n *\n *   const { modifiedCount } = await orders.updateMany(\n *     { status: 'pending' },\n *     { $set: { status: 'confirmed' } },\n *     { session },\n *   );\n * });\n */\nexport function withMongoTransaction<\n  T,\n  K = any,\n  Args extends Array<any> = any[],\n>(\n  connection: ConnectionValue,\n  fn: Callback<T, K, Args>,\n  options?: Omit<WithMongoTransactionOptions<any>, 'fn' | 'connection'>,\n): WithMongoTransactionWrapped<T, K, Args>;\n\nexport function withMongoTransaction(\n  connectionOrOptions: ConnectionValue | WithMongoTransactionOptions<any>,\n  maybeFn?: Callback<any>,\n  maybeOptions?: Partial<WithMongoTransactionOptions<any>>,\n): WithMongoTransactionWrapped<any> {\n  const {\n    connection: connectionValue,\n    fn,\n    sessionOptions = {},\n    timeoutMS,\n  } = prepareOptions(connectionOrOptions, maybeFn, maybeOptions);\n\n  return async function (this: any, ...args: any[]) {\n    const connection = isFunction(connectionValue)\n      ? await connectionValue()\n      : connectionValue;\n\n    const session = (await connection.startSession(\n      sessionOptions,\n    )) as ClientSession;\n\n    const scope = createTransactionScope(function (this: any, ...args: any[]) {\n      provideMongoSession(session);\n      return fn.call(this, session, ...args);\n    });\n\n    const timeoutAt = timeoutMS ? Date.now() + timeoutMS : 0;\n    const timeoutError = new MongoTransactionError(\n      'Transaction client-side timeout',\n    );\n\n    let [transactionError, transactionResult] = await catchError(() =>\n      session.withTransaction(async () => {\n        if (timeoutAt && timeoutAt < Date.now()) {\n          return Promise.reject(timeoutError);\n        }\n\n        await scope.run.apply(this, args);\n\n        if (scope.error) {\n          return Promise.reject(scope.error);\n        }\n      }),\n    );\n\n    const { result } = scope;\n\n    await session.endSession().catch(noop);\n\n    if (\n      transactionResult === undefined &&\n      isTransactionCommittedEmpty(session.transaction)\n    ) {\n      // do nothing here\n    } else if (\n      isTransactionAborted(session.transaction) &&\n      transactionResult === undefined &&\n      transactionError === undefined\n    ) {\n      transactionError = new MongoTransactionError(\n        'Transaction is explicitly aborted',\n      );\n    }\n\n    if (transactionError) {\n      await scope.rollback();\n      return Promise.reject(transactionError);\n    }\n\n    await scope.commit();\n\n    return result!;\n  };\n}\n\nfunction prepareOptions(\n  connectionOrOptions: ConnectionValue | WithMongoTransactionOptions<any>,\n  maybeFn?: Callback<any>,\n  maybeOptions?: Partial<WithMongoTransactionOptions<any>>,\n): WithMongoTransactionOptions<any> {\n  let options: WithMongoTransactionOptions<any>;\n\n  if (\n    isFunction(connectionOrOptions) ||\n    isMongoClientLike(connectionOrOptions)\n  ) {\n    options = {\n      ...(maybeOptions || {}),\n      connection: connectionOrOptions,\n      fn: maybeFn!,\n    };\n  } else {\n    options = connectionOrOptions;\n  }\n\n  return deepDefaults(options, {\n    sessionOptions: DEF_SESSION_OPTIONS,\n  });\n}\n","import { type RetryOnErrorConfig, noop, retryOnError } from '@andrew_l/toolkit';\nimport { createTransactionScope } from './scope';\n\nexport interface WithTransactionOptions extends Partial<RetryOnErrorConfig> {}\n\n/**\n * Wraps a function with transaction context, enabling retry logic and transactional effects.\n *\n * The wrapped function may be executed multiple times (up to `maxRetriesNumber`) to ensure\n * all side effects complete successfully. If the retries are exhausted without success,\n * registered cleanup functions will be executed to undo any applied effects.\n *\n * This utility is useful for managing transactional side effects, such as\n * updates to external systems, and ensures proper cleanup in case of failure.\n *\n * Additionally, this enables hooks like `useTransactionEffect()`, which allows\n * defining effects with automatic rollback mechanisms.\n *\n * @param fn - The target function to wrap with transaction handling.\n * @param [options] - Configuration options for the transaction handling.\n * @param [options.beforeRetryCallback] - An optional callback to execute before each retry attempt.\n * @param [options.shouldRetryBasedOnError] - A predicate to determine if a retry should occur based on the thrown error. Defaults to always retry.\n * @param [options.maxRetriesNumber=5] - The maximum number of retries before failing the transaction. Defaults to 5.\n * @param [options.delayFactor=0] - A multiplier for the delay between retries. Default is 0 (no exponential backoff).\n * @param [options.delayMaxMs=1000] - The maximum delay between retries, in milliseconds. Defaults to 1000 ms.\n * @param [options.delayMinMs=100] - The minimum delay between retries, in milliseconds. Defaults to 100 ms.\n *\n * @example\n * const confirmOrder = withTransaction(async (orderId) => {\n *   // Register Alert\n *   await useTransactionEffect(async () => {\n *     const alertId = await alertService.create({\n *       title: 'New Order: ' + orderId,\n *     });\n *\n *     return () => alertService.removeById(alertId); // Cleanup in case of failure\n *   });\n *\n *   // Update Statistics\n *   await useTransactionEffect(async () => {\n *     await statService.increment('orders_amount', 1);\n *\n *     return () => statService.decrement('orders_amount', 1); // Cleanup in case of failure\n *   });\n *\n *   // Simulate failure to trigger rollback\n *   throw new Error('Cancel transaction.');\n * });\n *\n * @group Main\n */\nexport function withTransaction<T, K = any, Args extends Array<any> = any[]>(\n  fn: (this: K, ...args: Args) => T,\n  {\n    beforeRetryCallback,\n    shouldRetryBasedOnError = () => true,\n    maxRetriesNumber = 5,\n    delayFactor = 0,\n    delayMaxMs = 1000,\n    delayMinMs = 100,\n  }: WithTransactionOptions = {},\n): (this: K, ...args: Args) => Promise<Awaited<T>> {\n  return async function (this: K, ...args: Args): Promise<Awaited<T>> {\n    const scope = createTransactionScope(fn);\n\n    await retryOnError(\n      {\n        beforeRetryCallback,\n        shouldRetryBasedOnError,\n        maxRetriesNumber,\n        delayFactor,\n        delayMaxMs,\n        delayMinMs,\n      },\n      async () => {\n        await scope.run.apply(this, args);\n\n        // explicitly reject to trigger retry\n        if (scope.error) {\n          return Promise.reject(scope.error);\n        }\n      },\n    )().catch(noop);\n\n    const { error, result } = scope;\n\n    if (error) {\n      await scope.rollback();\n      return Promise.reject(error) as any;\n    } else {\n      await scope.commit();\n    }\n\n    return result as Awaited<T>;\n  };\n}\n","import { createTransactionScope } from './scope';\n\nexport interface TransactionControlled<\n  T,\n  K = any,\n  Args extends Array<any> = any[],\n> {\n  run: (this: K, ...args: Args) => Promise<void>;\n\n  commit: () => Promise<void>;\n\n  rollback: () => Promise<void>;\n\n  result: Readonly<T | undefined>;\n\n  error: Readonly<Error | undefined>;\n\n  active: boolean;\n}\n\n/**\n * Wraps a function and returns a `TransactionControlled` interface, allowing manual control\n * over transaction commit and rollback operations.\n *\n * This provides finer-grained control over the transaction lifecycle, enabling users to\n * explicitly commit or rollback a transaction based on custom logic. It's especially useful\n * in scenarios where transactional state or conditions need to be externally determined.\n *\n * @example\n * const t = withTransactionControlled(async (userId) => {\n *   await useTransactionEffect(async () => {\n *     await db.users.updateById(userId, { premium: true });\n *\n *     return () => db.users.updateById(userId, { premium: false })\n *   });\n *\n *   const user = await db.users.findById(userId);\n *\n *   return user;\n * });\n *\n *\n * await t.run();\n *\n * // Remove premium when no subscriptions\n * if (t.result.activeSubscriptions > 0) {\n *   await t.commit();\n * } else {\n *   await t.rollback();\n * }\n *\n * @group Main\n */\nexport function withTransactionControlled<\n  T,\n  K = any,\n  Args extends Array<any> = any[],\n>(\n  fn: (this: K, ...args: Args) => T,\n): TransactionControlled<Awaited<T>, K, Args> {\n  const scope = createTransactionScope(fn);\n\n  const controlled = {\n    run(...args: Args) {\n      const self = this === controlled ? undefined : this;\n      return scope.run.apply(self, args);\n    },\n    commit() {\n      return scope.commit();\n    },\n    rollback() {\n      return scope.rollback();\n    },\n    get active() {\n      return scope.active;\n    },\n    get result() {\n      return scope.result;\n    },\n    get error() {\n      return scope.error;\n    },\n  };\n\n  return controlled;\n}\n"],"names":["args"],"mappings":"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"}