{"version":3,"sources":["../../src/hooks/internal/use-action-runner.ts","../../src/next/errors/redirect.ts","../../src/next/errors/http-access-fallback.ts","../../src/next/errors/framework.ts","../../src/next/errors/index.ts","../../src/core/redirect.ts","../../src/hooks/provider.tsx","../../src/hooks/internal/server-action-options.ts","../../src/hooks/use-server-action.ts","../../src/hooks/use-optimistic-action.ts"],"sourcesContent":["import { useCallback, useEffect, useLayoutEffect, useRef, useState, useTransition } from \"react\";\r\nimport { usePathname, useRouter } from \"next/navigation\";\r\nimport type {\r\n  ActionResult,\r\n  RedirectConfig,\r\n  ServerActionResponse,\r\n  ToastAdapter,\r\n} from \"../../types\";\r\nimport { isNextNavigationError, isRedirectError } from \"../../next/errors\";\r\nimport { getURLFromRedirectError } from \"../../next/errors/redirect\";\r\nimport { isSafeRedirectPath } from \"../../core/redirect\";\r\nimport { useActionForgeConfig } from \"../provider\";\r\n\r\n/** Options the runner reads on every call; the hooks translate theirs into these. */\r\nexport interface ActionRunnerOptions<TOutput> {\r\n  onSuccess?: (data: TOutput) => void | Promise<void>;\r\n  onError?: (result: ActionResult<TOutput>) => void | Promise<void>;\r\n  /** Message of the success toast for this result, or `undefined` for none. */\r\n  successToast?: (data: TOutput) => string | undefined;\r\n  /** Message of the error toast for this result, or `undefined` for none. */\r\n  errorToast?: (result: ActionResult<TOutput>) => string | undefined;\r\n  redirectOnAuthError?: boolean;\r\n  preventRedirect?: boolean;\r\n  redirectDelay?: number;\r\n  toast?: ToastAdapter;\r\n}\r\n\r\nexport interface RunOutcome<TOutput> {\r\n  result: ActionResult<TOutput>;\r\n  /** A Next.js navigation error to rethrow inside the caller's transition. */\r\n  rethrow?: unknown;\r\n}\r\n\r\nexport type RunnableAction<TOutput> = (...args: any[]) => Promise<ServerActionResponse<TOutput>>;\r\n\r\nlet warnedAboutMissingToast = false;\r\n\r\n/**\r\n * Whether following `target` from `pathname` changes what usePathname()\r\n * returns. An external target counts: the page unloads.\r\n */\r\nfunction leavesPathname(target: string, pathname: string): boolean {\r\n  try {\r\n    const from = new URL(pathname, \"http://next-action-forge.invalid\");\r\n    const to = new URL(target, from);\r\n    return to.origin !== from.origin || to.pathname !== from.pathname;\r\n  } catch {\r\n    return true;\r\n  }\r\n}\r\n\r\nfunction isResponse(value: unknown): value is ServerActionResponse<unknown> {\r\n  return typeof value === \"object\" && value !== null && \"success\" in value;\r\n}\r\n\r\nasync function runCallback<T>(name: string, callback: ((value: T) => unknown) | undefined, value: T) {\r\n  if (!callback) return;\r\n  try {\r\n    await callback(value);\r\n  } catch (error) {\r\n    // A bug in a consumer callback must not turn a completed action into a failure.\r\n    console.error(`[next-action-forge] The ${name} callback threw:`, error);\r\n  }\r\n}\r\n\r\n/**\r\n * Shared engine of the hooks: calls the action, maps its response to an\r\n * `ActionResult`, shows toasts, runs callbacks and follows redirects.\r\n *\r\n * - `run` does not start a transition, so callers can combine it with their\r\n *   own work in one transition (`useOptimisticAction`); they call\r\n *   `markStarted()` synchronously right before starting it.\r\n * - `execute` wraps `run` in a transition and rethrows `notFound()`,\r\n *   `forbidden()` and `unauthorized()` there, so Next's boundaries render.\r\n */\r\nexport function useActionRunner<TOutput>(\r\n  action: RunnableAction<TOutput>,\r\n  options: ActionRunnerOptions<TOutput>,\r\n) {\r\n  const router = useRouter();\r\n  const pathname = usePathname();\r\n  const config = useActionForgeConfig();\r\n\r\n  // Latest options and config, read at call time: execute stays stable even\r\n  // when callbacks are inline functions recreated on every render.\r\n  const optionsRef = useRef(options);\r\n  const toastRef = useRef<ToastAdapter | undefined>(options.toast ?? config.toast);\r\n  const pathnameRef = useRef(pathname);\r\n  useLayoutEffect(() => {\r\n    optionsRef.current = options;\r\n    toastRef.current = options.toast ?? config.toast;\r\n    pathnameRef.current = pathname;\r\n  });\r\n\r\n  const [result, setResult] = useState<ActionResult<TOutput>>();\r\n  const [isExecuting, setIsExecuting] = useState(false);\r\n  const pendingCalls = useRef(0);\r\n\r\n  // isRedirecting is derived, not synchronised by effects:\r\n  // - `redirectFrom` remembers the pathname a redirect started from. A server\r\n  //   redirect sets it only when it leads to another pathname, the one change\r\n  //   the hook can observe;\r\n  // - once the pathname differs, the redirect landed: `redirectFrom` is\r\n  //   cleared during render, so coming back to the page later does not\r\n  //   report it again. A new call clears it too (`markStarted`);\r\n  // - client navigations run in a transition that also clears `redirectFrom`,\r\n  //   so both flip back only when the navigation settles, a redirect to the\r\n  //   current URL included.\r\n  const [redirectFrom, setRedirectFrom] = useState<string | null>(null);\r\n  const [isNavigating, startNavigation] = useTransition();\r\n  const redirectTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\r\n  if (redirectFrom !== null && redirectFrom !== pathname) {\r\n    // Adjusting state while rendering: React re-renders right away, before\r\n    // the children see the stale value.\r\n    setRedirectFrom(null);\r\n  }\r\n  const isRedirecting = isNavigating || redirectFrom !== null;\r\n\r\n  useEffect(() => () => clearTimeout(redirectTimer.current), []);\r\n\r\n  const showToast = useCallback((kind: \"success\" | \"error\", message: string | undefined) => {\r\n    if (!message) return;\r\n    const toast = toastRef.current;\r\n    if (toast) {\r\n      toast[kind](message);\r\n    } else if (process.env.NODE_ENV === \"development\" && !warnedAboutMissingToast) {\r\n      warnedAboutMissingToast = true;\r\n      console.warn(\r\n        \"[next-action-forge] A toast was requested but no toast adapter is configured. \" +\r\n          \"Wrap your app in <ActionForgeProvider toast={toast}> or pass { toast } to the hook.\",\r\n      );\r\n    }\r\n  }, []);\r\n\r\n  const navigate = useCallback(\r\n    (target: RedirectConfig) => {\r\n      if (!isSafeRedirectPath(target.url)) {\r\n        console.error(\r\n          `[next-action-forge] Ignored a redirect to ${JSON.stringify(target.url)}: only same-origin paths are allowed.`,\r\n        );\r\n        return;\r\n      }\r\n      setRedirectFrom(pathnameRef.current);\r\n      const go = () =>\r\n        startNavigation(() => {\r\n          // Part of the navigation transition: commits when it settles.\r\n          setRedirectFrom(null);\r\n          if (target.replace) router.replace(target.url);\r\n          else router.push(target.url);\r\n        });\r\n      clearTimeout(redirectTimer.current);\r\n      if (target.delay && target.delay > 0) {\r\n        redirectTimer.current = setTimeout(go, target.delay);\r\n      } else {\r\n        go();\r\n      }\r\n    },\r\n    [router],\r\n  );\r\n\r\n  /**\r\n   * Mark a call as started. Must run synchronously before the transition\r\n   * that calls `run`: an update made inside a transition only commits when\r\n   * the transition ends, so the pending state would appear too late to\r\n   * disable a button against double submits.\r\n   */\r\n  const markStarted = useCallback(() => {\r\n    pendingCalls.current += 1;\r\n    setIsExecuting(true);\r\n    // A server redirect that never landed is not pending anymore.\r\n    setRedirectFrom(null);\r\n  }, []);\r\n\r\n  /** Call the action; `markStarted()` must have been called first. */\r\n  const run = useCallback(\r\n    async (input: unknown): Promise<RunOutcome<TOutput>> => {\r\n      const opts = optionsRef.current;\r\n\r\n      let response: unknown;\r\n      let thrown: unknown;\r\n      let didThrow = false;\r\n      try {\r\n        response = await (input === undefined ? action() : action(input));\r\n      } catch (error) {\r\n        didThrow = true;\r\n        thrown = error;\r\n      } finally {\r\n        pendingCalls.current -= 1;\r\n        if (pendingCalls.current === 0) setIsExecuting(false);\r\n      }\r\n\r\n      if (didThrow) {\r\n        if (isRedirectError(thrown)) {\r\n          // Next performs the navigation itself; the rejection only settles the call.\r\n          const navigation: ActionResult<TOutput> = { status: \"navigation\" };\r\n          setResult(navigation);\r\n          // A redirect that keeps the pathname (new search params only) ends\r\n          // without any change the hook could wait for: nothing to report.\r\n          const from = pathnameRef.current;\r\n          if (leavesPathname(getURLFromRedirectError(thrown), from)) setRedirectFrom(from);\r\n          return { result: navigation };\r\n        }\r\n        if (isNextNavigationError(thrown)) {\r\n          const navigation: ActionResult<TOutput> = { status: \"navigation\" };\r\n          setResult(navigation);\r\n          return { result: navigation, rethrow: thrown };\r\n        }\r\n        const failure: ActionResult<TOutput> = {\r\n          status: \"error\",\r\n          fetchError: thrown instanceof Error ? thrown.message : \"Network error\",\r\n        };\r\n        setResult(failure);\r\n        showToast(\"error\", opts.errorToast?.(failure));\r\n        await runCallback(\"onError\", opts.onError, failure);\r\n        return { result: failure };\r\n      }\r\n\r\n      if (!isResponse(response)) {\r\n        // Next.js resolves a Server Action to undefined on some redirect paths,\r\n        // without telling where to: assume another page.\r\n        const navigation: ActionResult<TOutput> = { status: \"navigation\" };\r\n        setResult(navigation);\r\n        setRedirectFrom(pathnameRef.current);\r\n        return { result: navigation };\r\n      }\r\n\r\n      if (response.success) {\r\n        const data = response.data as TOutput;\r\n        const success: ActionResult<TOutput> = { status: \"success\", data };\r\n        setResult(success);\r\n        showToast(\"success\", opts.successToast?.(data));\r\n        await runCallback(\"onSuccess\", opts.onSuccess, data);\r\n        if (response.redirect && !opts.preventRedirect) {\r\n          const target =\r\n            typeof response.redirect === \"string\" ? { url: response.redirect } : response.redirect;\r\n          navigate({ ...target, delay: target.delay ?? opts.redirectDelay });\r\n        }\r\n        return { result: success };\r\n      }\r\n\r\n      const error = response.error;\r\n      const failure: ActionResult<TOutput> = {\r\n        status: \"error\",\r\n        serverError: error,\r\n        validationErrors: error.fields,\r\n      };\r\n      setResult(failure);\r\n      showToast(\"error\", opts.errorToast?.(failure));\r\n      await runCallback(\"onError\", opts.onError, failure);\r\n      if ((opts.redirectOnAuthError ?? true) && error.shouldRedirect) {\r\n        navigate({ url: error.redirectTo ?? \"/login\" });\r\n      }\r\n      return { result: failure };\r\n    },\r\n    [action, navigate, showToast],\r\n  );\r\n\r\n  const [, startTransition] = useTransition();\r\n\r\n  const execute = useCallback(\r\n    (input?: unknown) => {\r\n      markStarted();\r\n      return new Promise<ActionResult<TOutput>>((resolve) => {\r\n        startTransition(async () => {\r\n          const outcome = await run(input);\r\n          resolve(outcome.result);\r\n          if (outcome.rethrow !== undefined) {\r\n            // Unhandled errors in a transition reach the nearest error\r\n            // boundary, which is how notFound() renders its page.\r\n            throw outcome.rethrow;\r\n          }\r\n        });\r\n      });\r\n    },\r\n    [markStarted, run],\r\n  );\r\n\r\n  const reset = useCallback(() => {\r\n    clearTimeout(redirectTimer.current);\r\n    setResult(undefined);\r\n    setRedirectFrom(null);\r\n  }, []);\r\n\r\n  return {\r\n    markStarted,\r\n    run,\r\n    execute,\r\n    result,\r\n    isExecuting,\r\n    isRedirecting,\r\n    reset,\r\n  };\r\n}\r\n","// Comes from: https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/redirect-error.ts\r\n\r\nenum RedirectStatusCode {\r\n\tSeeOther = 303,\r\n\tTemporaryRedirect = 307,\r\n\tPermanentRedirect = 308,\r\n}\r\n\r\nconst REDIRECT_ERROR_CODE = \"NEXT_REDIRECT\";\r\n\r\nenum RedirectType {\r\n\tpush = \"push\",\r\n\treplace = \"replace\",\r\n}\r\n\r\nexport type RedirectError = Error & {\r\n\tdigest: `${typeof REDIRECT_ERROR_CODE};${RedirectType};${string};${RedirectStatusCode};`;\r\n};\r\n\r\n/**\r\n * Checks an error to determine if it's an error generated by the\r\n * `redirect(url)` helper.\r\n *\r\n * @param error the error that may reference a redirect error\r\n * @returns true if the error is a redirect error\r\n */\r\nexport function isRedirectError(error: unknown): error is RedirectError {\r\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tconst digest = error.digest.split(\";\");\r\n\tconst [errorCode, type] = digest;\r\n\tconst destination = digest.slice(2, -2).join(\";\");\r\n\tconst status = digest.at(-2);\r\n\r\n\tconst statusCode = Number(status);\r\n\r\n\treturn (\r\n\t\terrorCode === REDIRECT_ERROR_CODE &&\r\n\t\t(type === \"replace\" || type === \"push\") &&\r\n\t\ttypeof destination === \"string\" &&\r\n\t\t!isNaN(statusCode) &&\r\n\t\tstatusCode in RedirectStatusCode\r\n\t);\r\n}\r\n\r\n/**\r\n * The destination of a redirect error. For a Server Action call that\r\n * redirected, Next.js puts there the path and search it navigates to\r\n * (without the base path), or the full URL of an external target.\r\n */\r\nexport function getURLFromRedirectError(error: RedirectError): string {\r\n\treturn error.digest.split(\";\").slice(2, -2).join(\";\");\r\n}","// Comes from https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/http-access-fallback/http-access-fallback.ts\r\n\r\nconst HTTPAccessErrorStatus = {\r\n\tNOT_FOUND: 404,\r\n\tFORBIDDEN: 403,\r\n\tUNAUTHORIZED: 401,\r\n};\r\n\r\nconst ALLOWED_CODES = new Set(Object.values(HTTPAccessErrorStatus));\r\n\r\nconst HTTP_ERROR_FALLBACK_ERROR_CODE = \"NEXT_HTTP_ERROR_FALLBACK\";\r\n\r\nexport type HTTPAccessFallbackError = Error & {\r\n\tdigest: `${typeof HTTP_ERROR_FALLBACK_ERROR_CODE};${string}`;\r\n};\r\n\r\n/**\r\n * Checks an error to determine if it's an error generated by\r\n * the HTTP navigation APIs `notFound()`, `forbidden()` or `unauthorized()`.\r\n *\r\n * @param error the error that may reference a HTTP access error\r\n * @returns true if the error is a HTTP access error\r\n */\r\nexport function isHTTPAccessFallbackError(error: unknown): error is HTTPAccessFallbackError {\r\n\tif (typeof error !== \"object\" || error === null || !(\"digest\" in error) || typeof error.digest !== \"string\") {\r\n\t\treturn false;\r\n\t}\r\n\tconst [prefix, httpStatus] = error.digest.split(\";\");\r\n\r\n\treturn prefix === HTTP_ERROR_FALLBACK_ERROR_CODE && ALLOWED_CODES.has(Number(httpStatus));\r\n}\r\n\r\nexport function getAccessFallbackHTTPStatus(error: HTTPAccessFallbackError): number {\r\n\tconst httpStatus = error.digest.split(\";\")[1];\r\n\treturn Number(httpStatus);\r\n}","// Mirrors of the checks behind `unstable_rethrow` in next/navigation\r\n// (Next.js 16.3: client/components/unstable-rethrow.server.js and the\r\n// modules it imports). They are copied rather than imported because plain\r\n// Node ESM cannot resolve \"next/navigation\" (Next ships no \"exports\" map),\r\n// which would break this package's ESM build outside a bundler.\r\n\r\nfunction hasDigest(error: unknown): error is { digest: string } {\r\n  return (\r\n    typeof error === \"object\" &&\r\n    error !== null &&\r\n    \"digest\" in error &&\r\n    typeof (error as { digest: unknown }).digest === \"string\"\r\n  );\r\n}\r\n\r\n/** `notFound()` on Next.js 14 and 15.0, before NEXT_HTTP_ERROR_FALLBACK. */\r\nexport function isLegacyNotFoundError(error: unknown): boolean {\r\n  return hasDigest(error) && error.digest === \"NEXT_NOT_FOUND\";\r\n}\r\n\r\n/** Dynamic API used while prerendering (hooks-server-context). */\r\nexport function isDynamicServerError(error: unknown): boolean {\r\n  return hasDigest(error) && error.digest === \"DYNAMIC_SERVER_USAGE\";\r\n}\r\n\r\n/** `useSearchParams()` and friends opting a subtree out of prerendering. */\r\nexport function isBailoutToCSRError(error: unknown): boolean {\r\n  return hasDigest(error) && error.digest === \"BAILOUT_TO_CLIENT_SIDE_RENDERING\";\r\n}\r\n\r\n/** Prerendering stopped a promise that will never settle (cache components). */\r\nexport function isHangingPromiseRejectionError(error: unknown): boolean {\r\n  return hasDigest(error) && error.digest === \"HANGING_PROMISE_REJECTION\";\r\n}\r\n\r\n/** Prerendering interrupted by dynamic access (cache components). */\r\nexport function isPrerenderInterruptedError(error: unknown): boolean {\r\n  return (\r\n    hasDigest(error) &&\r\n    error.digest === \"NEXT_PRERENDER_INTERRUPTED\" &&\r\n    error instanceof Error\r\n  );\r\n}\r\n\r\n/** React's postpone signal used by partial prerendering. */\r\nexport function isPostpone(error: unknown): boolean {\r\n  return (\r\n    typeof error === \"object\" &&\r\n    error !== null &&\r\n    (error as { $$typeof?: unknown }).$$typeof === Symbol.for(\"react.postpone\")\r\n  );\r\n}\r\n\r\n/** Partial prerendering postponing because a dynamic API was used. */\r\nexport function isDynamicPostpone(error: unknown): boolean {\r\n  if (typeof error !== \"object\" || error === null) return false;\r\n  const message = (error as { message?: unknown }).message;\r\n  return (\r\n    typeof message === \"string\" &&\r\n    message.includes(\"needs to bail out of prerendering at this point because it used\") &&\r\n    message.includes(\"Learn more: https://nextjs.org/docs/messages/ppr-caught-error\")\r\n  );\r\n}\r\n","import { isRedirectError } from \"./redirect\";\r\nimport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\r\nimport {\r\n  isBailoutToCSRError,\r\n  isDynamicPostpone,\r\n  isDynamicServerError,\r\n  isHangingPromiseRejectionError,\r\n  isLegacyNotFoundError,\r\n  isPostpone,\r\n  isPrerenderInterruptedError,\r\n} from \"./framework\";\r\n\r\nexport { isRedirectError } from \"./redirect\";\r\nexport type { RedirectError } from \"./redirect\";\r\n\r\nexport { isHTTPAccessFallbackError, getAccessFallbackHTTPStatus } from \"./http-access-fallback\";\r\nexport type { HTTPAccessFallbackError } from \"./http-access-fallback\";\r\n\r\n/**\r\n * Checks if the error is a navigation error that should be re-thrown:\r\n * `redirect()`, `permanentRedirect()`, `notFound()`, `forbidden()` and\r\n * `unauthorized()`, including the `notFound()` digest of Next.js 14 and 15.0.\r\n */\r\nexport function isNextNavigationError(error: unknown): boolean {\r\n\treturn isRedirectError(error) || isHTTPAccessFallbackError(error) || isLegacyNotFoundError(error);\r\n}\r\n\r\n/**\r\n * Checks if the error is a notFound error\r\n * Note: Next.js implements notFound() using HTTP_ERROR_FALLBACK with status 404,\r\n * not as a separate error type like NEXT_REDIRECT (Next.js 14 and 15.0 used\r\n * the NEXT_NOT_FOUND digest instead).\r\n */\r\nexport function isNotFoundError(error: unknown): boolean {\r\n\treturn (\r\n\t\tisLegacyNotFoundError(error) ||\r\n\t\t(isHTTPAccessFallbackError(error) && getAccessFallbackHTTPStatus(error) === 404)\r\n\t);\r\n}\r\n\r\n/**\r\n * Whether the error is Next.js control flow that user code must never\r\n * swallow: navigation errors plus the signals Next uses while rendering\r\n * (dynamic usage, client-side-rendering bailouts, postpones). The same set\r\n * `unstable_rethrow` from next/navigation checks.\r\n */\r\nexport function isNextInternalError(error: unknown): boolean {\r\n\treturn (\r\n\t\tisNextNavigationError(error) ||\r\n\t\tisBailoutToCSRError(error) ||\r\n\t\tisDynamicServerError(error) ||\r\n\t\tisDynamicPostpone(error) ||\r\n\t\tisPostpone(error) ||\r\n\t\tisHangingPromiseRejectionError(error) ||\r\n\t\tisPrerenderInterruptedError(error)\r\n\t);\r\n}\r\n\r\nconst MAX_CAUSE_DEPTH = 10;\r\n\r\n/**\r\n * Rethrow the error, or the first error in its `cause` chain, when it is\r\n * Next.js control flow. Mirrors `unstable_rethrow`, so an action called from\r\n * a Server Component keeps redirects, `notFound()` and prerendering bailouts\r\n * working even when user code wraps them in another error.\r\n */\r\nexport function rethrowIfNextInternal(error: unknown): void {\r\n\tlet current: unknown = error;\r\n\tfor (let depth = 0; depth < MAX_CAUSE_DEPTH && current !== undefined && current !== null; depth++) {\r\n\t\tif (isNextInternalError(current)) {\r\n\t\t\tthrow current;\r\n\t\t}\r\n\t\tcurrent = current instanceof Error ? current.cause : undefined;\r\n\t}\r\n}\r\n","import type { ActionLogger, RedirectSpec, RedirectTarget } from \"../types\";\r\n\r\nexport type { RedirectSpec } from \"../types\";\r\nimport { describeAction } from \"./logger\";\r\n\r\nconst PARSE_BASE = \"http://next-action-forge.invalid\";\r\n\r\n// Browsers strip tabs and newlines from URLs before parsing them, so a path\r\n// such as \"/\\t/evil.example\" would turn into the protocol-relative\r\n// \"//evil.example\". Any control character is rejected outright.\r\n// eslint-disable-next-line no-control-regex -- matching control characters is the point.\r\nconst CONTROL_CHARACTERS = /[\\u0000-\\u001F\\u007F]/;\r\n\r\n/**\r\n * Whether `value` is a same-origin path that is safe to navigate to: it\r\n * starts with a single \"/\" and, once parsed the way a browser parses it,\r\n * still points to the current origin. Rejects absolute and\r\n * protocol-relative URLs, backslash tricks (\"/\\\\evil.example\") and control\r\n * characters.\r\n */\r\nexport function isSafeRedirectPath(value: unknown): value is string {\r\n  if (typeof value !== \"string\" || !value.startsWith(\"/\")) return false;\r\n  if (value[1] === \"/\" || value[1] === \"\\\\\") return false;\r\n  if (CONTROL_CHARACTERS.test(value)) return false;\r\n  try {\r\n    return new URL(value, PARSE_BASE).origin === PARSE_BASE;\r\n  } catch {\r\n    return false;\r\n  }\r\n}\r\n\r\n/** Throws at definition time when a static redirect points outside the app. */\r\nexport function assertSafeRedirectPath(url: unknown, source: string): void {\r\n  if (!isSafeRedirectPath(url)) {\r\n    throw new TypeError(\r\n      `[next-action-forge] ${source} only accepts a same-origin path starting with \"/\", received ${JSON.stringify(url)}. ` +\r\n        `Use redirect() from next/navigation inside the handler to leave the app.`,\r\n    );\r\n  }\r\n}\r\n\r\n/** Validate a fixed target at definition time; callbacks are checked on each call. */\r\nexport function assertStaticRedirect(spec: RedirectSpec | undefined, source: string): void {\r\n  if (typeof spec === \"string\") {\r\n    assertSafeRedirectPath(spec, source);\r\n  } else if (typeof spec === \"object\" && spec !== null) {\r\n    assertSafeRedirectPath(spec.url, source);\r\n  }\r\n}\r\n\r\n/**\r\n * Resolve the redirect attached to a successful result. The callback may be\r\n * async. A callback that throws or returns an unsafe target is logged and\r\n * yields no redirect: the mutation already happened, so the success must\r\n * still reach the client.\r\n */\r\nexport async function resolveRedirect(\r\n  spec: RedirectSpec | undefined,\r\n  output: unknown,\r\n  logger: ActionLogger,\r\n  actionName: string | undefined,\r\n): Promise<RedirectTarget | undefined> {\r\n  if (!spec) return undefined;\r\n\r\n  let value: RedirectTarget | undefined;\r\n  try {\r\n    value = typeof spec === \"function\" ? await spec(output) : spec;\r\n  } catch (error) {\r\n    logger.error(`[next-action-forge] The redirect callback threw${describeAction(actionName)}:`, error);\r\n    return undefined;\r\n  }\r\n\r\n  if (value === undefined || value === null) return undefined;\r\n\r\n  const url = typeof value === \"string\" ? value : value.url;\r\n  if (!isSafeRedirectPath(url)) {\r\n    logger.error(\r\n      `[next-action-forge] Ignored a redirect to ${JSON.stringify(url)}${describeAction(actionName)}: only same-origin paths are allowed.`,\r\n    );\r\n    return undefined;\r\n  }\r\n  return value;\r\n}\r\n","import { createContext, useContext, useMemo, type Context, type ReactNode } from \"react\";\r\nimport type { ToastAdapter } from \"../types\";\r\n\r\nexport interface ActionForgeConfig {\r\n  /** Shows the success and error toasts requested by the hooks. */\r\n  toast?: ToastAdapter;\r\n}\r\n\r\n// The hooks ship in two entry points (next-action-forge/hooks and\r\n// next-action-forge/hooks/form), each bundled with its own copy of this\r\n// module. A global symbol gives both copies the same context object, so one\r\n// provider serves every hook.\r\nconst CONTEXT_KEY = Symbol.for(\"next-action-forge.config\");\r\nconst globalStore = globalThis as { [CONTEXT_KEY]?: Context<ActionForgeConfig> };\r\nconst ActionForgeContext: Context<ActionForgeConfig> =\r\n  globalStore[CONTEXT_KEY] ?? (globalStore[CONTEXT_KEY] = createContext<ActionForgeConfig>({}));\r\n\r\nexport interface ActionForgeProviderProps extends ActionForgeConfig {\r\n  children: ReactNode;\r\n}\r\n\r\n/**\r\n * Configures every next-action-forge hook below it. Render it inside a\r\n * Client Component, because `toast` is a function:\r\n *\r\n * ```tsx\r\n * \"use client\";\r\n * import { toast } from \"sonner\";\r\n * import { ActionForgeProvider } from \"next-action-forge/hooks\";\r\n *\r\n * export function Providers({ children }: { children: React.ReactNode }) {\r\n *   return <ActionForgeProvider toast={toast}>{children}</ActionForgeProvider>;\r\n * }\r\n * ```\r\n */\r\nexport function ActionForgeProvider({ toast, children }: ActionForgeProviderProps) {\r\n  const value = useMemo<ActionForgeConfig>(() => ({ toast }), [toast]);\r\n  return <ActionForgeContext.Provider value={value}>{children}</ActionForgeContext.Provider>;\r\n}\r\n\r\nexport function useActionForgeConfig(): ActionForgeConfig {\r\n  return useContext(ActionForgeContext);\r\n}\r\n","import type { ActionResult, ToastAdapter } from \"../../types\";\r\nimport type { ActionRunnerOptions } from \"./use-action-runner\";\r\n\r\nexport interface UseServerActionOptions<TOutput> {\r\n  onSuccess?: (data: TOutput) => void | Promise<void>;\r\n  onError?: (error: ActionResult<TOutput>) => void | Promise<void>;\r\n\r\n  /** Message of the success toast when `showSuccessToast` is `true`. */\r\n  successMessage?: string | ((data: TOutput) => string);\r\n  /** Message of the error toast; defaults to the server error or fetch error message. */\r\n  errorMessage?: string | ((error: ActionResult<TOutput>) => string);\r\n  /** `true` (uses `successMessage`, or \"Success!\"), a message, or a function returning it. */\r\n  showSuccessToast?: boolean | string | ((data: TOutput) => string);\r\n  /** Default `true`. */\r\n  showErrorToast?: boolean;\r\n  /** Overrides the adapter of `<ActionForgeProvider>` for this hook. */\r\n  toast?: ToastAdapter;\r\n\r\n  /** Follow `shouldRedirect`/`redirectTo` on authentication errors. Default `true`. */\r\n  redirectOnAuthError?: boolean;\r\n  /** Ignore the redirect returned by the action. Default `false`. */\r\n  preventRedirect?: boolean;\r\n  /** Delay in ms before following a redirect without its own `delay`. Default `0`. */\r\n  redirectDelay?: number;\r\n}\r\n\r\nfunction successToastMessage<TOutput>(\r\n  options: UseServerActionOptions<TOutput>,\r\n  data: TOutput,\r\n): string | undefined {\r\n  const { showSuccessToast = false, successMessage } = options;\r\n  if (!showSuccessToast) return undefined;\r\n  if (typeof showSuccessToast === \"string\") return showSuccessToast;\r\n  if (typeof showSuccessToast === \"function\") return showSuccessToast(data);\r\n  if (successMessage) {\r\n    return typeof successMessage === \"function\" ? successMessage(data) : successMessage;\r\n  }\r\n  return \"Success!\";\r\n}\r\n\r\nfunction errorToastMessage<TOutput>(\r\n  options: UseServerActionOptions<TOutput>,\r\n  result: ActionResult<TOutput>,\r\n): string | undefined {\r\n  const { showErrorToast = true, errorMessage } = options;\r\n  if (!showErrorToast) return undefined;\r\n  if (errorMessage) {\r\n    return typeof errorMessage === \"function\" ? errorMessage(result) : errorMessage;\r\n  }\r\n  return result.serverError?.message || result.fetchError || \"An error occurred\";\r\n}\r\n\r\n/** Translate the public hook options into the runner's. */\r\nexport function toRunnerOptions<TOutput>(\r\n  options: UseServerActionOptions<TOutput>,\r\n): ActionRunnerOptions<TOutput> {\r\n  return {\r\n    onSuccess: options.onSuccess,\r\n    onError: options.onError,\r\n    successToast: (data) => successToastMessage(options, data),\r\n    errorToast: (result) => errorToastMessage(options, result),\r\n    redirectOnAuthError: options.redirectOnAuthError,\r\n    preventRedirect: options.preventRedirect,\r\n    redirectDelay: options.redirectDelay,\r\n    toast: options.toast,\r\n  };\r\n}\r\n","import type { ServerAction, ActionResult } from \"../types\";\r\nimport { useActionRunner, type RunnableAction } from \"./internal/use-action-runner\";\r\nimport { toRunnerOptions, type UseServerActionOptions } from \"./internal/server-action-options\";\r\n\r\nexport type { UseServerActionOptions } from \"./internal/server-action-options\";\r\n\r\nexport interface UseServerActionReturn<TInput, TOutput> {\r\n  execute: TInput extends void\r\n    ? () => Promise<ActionResult<TOutput>>\r\n    : (input: TInput) => Promise<ActionResult<TOutput>>;\r\n\r\n  result: ActionResult<TOutput> | undefined;\r\n  isExecuting: boolean;\r\n  isRedirecting: boolean;\r\n  hasSucceeded: boolean;\r\n  hasErrored: boolean;\r\n\r\n  reset: () => void;\r\n}\r\n\r\n// Overload for void actions\r\nexport function useServerAction<TOutput>(\r\n  action: ServerAction<void, TOutput>,\r\n  options?: UseServerActionOptions<TOutput>\r\n): UseServerActionReturn<void, TOutput>;\r\n\r\n// Overload for actions with input\r\nexport function useServerAction<TInput, TOutput>(\r\n  action: ServerAction<TInput, TOutput>,\r\n  options?: UseServerActionOptions<TOutput>\r\n): UseServerActionReturn<TInput, TOutput>;\r\n\r\n/**\r\n * Run a server action from a Client Component: loading and redirect state,\r\n * the last result, toasts through the configured adapter, callbacks, and\r\n * redirects returned by the action (same-origin paths only).\r\n */\r\nexport function useServerAction<TInput, TOutput>(\r\n  action: ServerAction<TInput, TOutput>,\r\n  options: UseServerActionOptions<TOutput> = {}\r\n): UseServerActionReturn<TInput, TOutput> {\r\n  const runner = useActionRunner<TOutput>(action as RunnableAction<TOutput>, toRunnerOptions(options));\r\n\r\n  return {\r\n    execute: runner.execute as UseServerActionReturn<TInput, TOutput>[\"execute\"],\r\n    result: runner.result,\r\n    isExecuting: runner.isExecuting,\r\n    isRedirecting: runner.isRedirecting,\r\n    hasSucceeded: runner.result?.status === \"success\",\r\n    hasErrored: runner.result?.status === \"error\",\r\n    reset: runner.reset,\r\n  };\r\n}\r\n","import { useCallback, useLayoutEffect, useOptimistic, useRef, useTransition } from \"react\";\r\nimport type { ServerAction, ActionResult } from \"../types\";\r\nimport { useActionRunner, type RunnableAction } from \"./internal/use-action-runner\";\r\nimport { toRunnerOptions, type UseServerActionOptions } from \"./internal/server-action-options\";\r\n\r\nexport interface UseOptimisticActionOptions<TInput, TOutput, TOptimistic> extends UseServerActionOptions<TOutput> {\r\n  /**\r\n   * Compute the optimistic state from the current one and the input. It must\r\n   * be pure: React may call it again while the action is pending.\r\n   */\r\n  updateFn: TInput extends void\r\n    ? (current: TOptimistic) => TOptimistic\r\n    : (current: TOptimistic, input: TInput) => TOptimistic;\r\n}\r\n\r\nexport interface UseOptimisticActionReturn<TInput, TOutput, TOptimistic> {\r\n  /**\r\n   * The optimistic state while the action is pending, otherwise the state\r\n   * passed to the hook. Refresh that state (for example with\r\n   * `revalidatePath` in the action) so it reflects the result once done.\r\n   */\r\n  optimisticState: TOptimistic;\r\n\r\n  /**\r\n   * Execute the action with optimistic update\r\n   */\r\n  execute: TInput extends void\r\n    ? () => Promise<ActionResult<TOutput>>\r\n    : (input: TInput) => Promise<ActionResult<TOutput>>;\r\n\r\n  isExecuting: boolean;\r\n  isRedirecting: boolean;\r\n  hasSucceeded: boolean;\r\n  hasErrored: boolean;\r\n  result: ActionResult<TOutput> | undefined;\r\n  reset: () => void;\r\n}\r\n\r\n/**\r\n * Hook for server actions with optimistic updates. The optimistic update and\r\n * the server call run in one transition, as React's `useOptimistic`\r\n * requires, so the optimistic state stays visible until the action settles.\r\n *\r\n * @example\r\n * ```typescript\r\n * const { optimisticState, execute } = useOptimisticAction(\r\n *   todos,\r\n *   toggleTodoAction,\r\n *   { updateFn: (todos, { id }) => todos.map((t) => (t.id === id ? { ...t, done: !t.done } : t)) },\r\n * );\r\n * ```\r\n */\r\n// Overload for actions without input: execute() takes no argument.\r\nexport function useOptimisticAction<TOutput, TOptimistic>(\r\n  initialState: TOptimistic,\r\n  action: ServerAction<void, TOutput>,\r\n  options: UseOptimisticActionOptions<void, TOutput, TOptimistic>\r\n): UseOptimisticActionReturn<void, TOutput, TOptimistic>;\r\n\r\n// Overload for actions with input\r\nexport function useOptimisticAction<TInput, TOutput, TOptimistic>(\r\n  initialState: TOptimistic,\r\n  action: ServerAction<TInput, TOutput>,\r\n  options: UseOptimisticActionOptions<TInput, TOutput, TOptimistic>\r\n): UseOptimisticActionReturn<TInput, TOutput, TOptimistic>;\r\n\r\nexport function useOptimisticAction<TInput, TOutput, TOptimistic>(\r\n  initialState: TOptimistic,\r\n  action: ServerAction<TInput, TOutput>,\r\n  options: UseOptimisticActionOptions<TInput, TOutput, TOptimistic>\r\n): UseOptimisticActionReturn<TInput, TOutput, TOptimistic> {\r\n  const { updateFn, ...serverActionOptions } = options;\r\n  const [optimisticState, addOptimistic] = useOptimistic(\r\n    initialState,\r\n    updateFn as (current: TOptimistic, input: TInput) => TOptimistic,\r\n  );\r\n  const runner = useActionRunner<TOutput>(\r\n    action as RunnableAction<TOutput>,\r\n    toRunnerOptions(serverActionOptions),\r\n  );\r\n  const [, startTransition] = useTransition();\r\n\r\n  // Read the latest setter at call time so execute keeps a stable identity.\r\n  const addOptimisticRef = useRef(addOptimistic);\r\n  useLayoutEffect(() => {\r\n    addOptimisticRef.current = addOptimistic;\r\n  });\r\n\r\n  const { markStarted, run } = runner;\r\n  const execute = useCallback(\r\n    (input?: TInput) => {\r\n      markStarted();\r\n      return new Promise<ActionResult<TOutput>>((resolve) => {\r\n        startTransition(async () => {\r\n          addOptimisticRef.current(input as TInput);\r\n          const outcome = await run(input);\r\n          resolve(outcome.result);\r\n          if (outcome.rethrow !== undefined) throw outcome.rethrow;\r\n        });\r\n      });\r\n    },\r\n    [markStarted, run],\r\n  );\r\n\r\n  return {\r\n    optimisticState,\r\n    execute: execute as UseOptimisticActionReturn<TInput, TOutput, TOptimistic>[\"execute\"],\r\n    isExecuting: runner.isExecuting,\r\n    isRedirecting: runner.isRedirecting,\r\n    hasSucceeded: runner.result?.status === \"success\",\r\n    hasErrored: runner.result?.status === \"error\",\r\n    result: runner.result,\r\n    reset: runner.reset,\r\n  };\r\n}\r\n"],"mappings":"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","names":["RedirectStatusCode","error","failure","useCallback","useLayoutEffect","useRef","useTransition","useTransition","useRef","useLayoutEffect","useCallback"]}