next-safe-action
Version:
Type safe and validated Server Actions in your Next.js project.
118 lines (115 loc) • 3.38 kB
JavaScript
import { t as FrameworkErrorHandler } from "./errors-BsNXg-5Q.mjs";
import * as React from "react";
//#region src/hooks-utils.ts
const getActionStatus = ({ isIdle, isExecuting, isTransitioning, result, hasNavigated, hasThrownError }) => {
if (isIdle) return "idle";
else if (isExecuting) return "executing";
else if (isTransitioning) return "transitioning";
else if (
hasThrownError ||
typeof result.validationErrors !== "undefined" ||
typeof result.serverError !== "undefined"
)
return "hasErrored";
else if (hasNavigated) return "hasNavigated";
else return "hasSucceeded";
};
const getActionShorthandStatusObject = (status) => {
return {
isIdle: status === "idle",
isExecuting: status === "executing",
isTransitioning: status === "transitioning",
isPending: status === "executing" || status === "transitioning",
hasSucceeded: status === "hasSucceeded",
hasErrored: status === "hasErrored",
hasNavigated: status === "hasNavigated",
};
};
/**
* Converts a callback to a ref to avoid triggering re-renders when passed as a
* prop or avoid re-executing effects when passed as a dependency
*/
function useCallbackRef(callback) {
const callbackRef = React.useRef(callback);
React.useEffect(() => {
callbackRef.current = callback;
});
return React.useMemo(() => (arg) => callbackRef.current?.(arg), []);
}
const useActionCallbacks = ({ result, input, status, cb, navigationError, thrownError }) => {
const onExecute = useCallbackRef(cb?.onExecute);
const onSuccess = useCallbackRef(cb?.onSuccess);
const onError = useCallbackRef(cb?.onError);
const onSettled = useCallbackRef(cb?.onSettled);
const onNavigation = useCallbackRef(cb?.onNavigation);
React.useEffect(() => {
const executeCallbacks = async () => {
switch (status) {
case "executing":
await Promise.resolve(onExecute?.({ input })).then(() => {});
break;
case "transitioning":
break;
case "hasSucceeded":
if (navigationError || thrownError) break;
await Promise.all([
Promise.resolve(
onSuccess?.({
data: result.data,
input,
})
),
Promise.resolve(
onSettled?.({
result,
input,
})
),
]);
break;
case "hasErrored":
await Promise.all([
Promise.resolve(
onError?.({
error: {
...result,
...(thrownError ? { thrownError } : {}),
},
input,
})
),
Promise.resolve(
onSettled?.({
result,
input,
})
),
]);
break;
}
if (!navigationError) return;
if (FrameworkErrorHandler.getNavigationKind(navigationError) === "redirect" || status === "hasNavigated") {
const navigationKind = FrameworkErrorHandler.getNavigationKind(navigationError);
await Promise.all([
Promise.resolve(
onNavigation?.({
input,
navigationKind,
})
),
Promise.resolve(
onSettled?.({
result,
input,
navigationKind,
})
),
]);
}
};
executeCallbacks().catch(console.error);
}, [input, status, result, navigationError, thrownError, onExecute, onSuccess, onSettled, onError, onNavigation]);
};
//#endregion
export { getActionStatus as n, useActionCallbacks as r, getActionShorthandStatusObject as t };
//# sourceMappingURL=hooks-utils-DA2xDVWH.mjs.map