next-safe-action
Version:
Type safe and validated Server Actions in your Next.js project.
1 lines • 6.46 kB
Source Map (JSON)
{"version":3,"file":"hooks-utils-DA2xDVWH.mjs","names":[],"sources":["../src/hooks-utils.ts"],"sourcesContent":["import * as React from \"react\";\nimport type { HookActionStatus, HookCallbacks, HookShorthandStatus } from \"./hooks.types\";\nimport type { SafeActionResult } from \"./index.types\";\nimport { FrameworkErrorHandler } from \"./next/errors\";\nimport type { InferInputOrDefault, StandardSchemaV1 } from \"./standard-schema\";\n\nexport const getActionStatus = <ServerError, S extends StandardSchemaV1 | undefined, CVE, Data>({\n\tisIdle,\n\tisExecuting,\n\tisTransitioning,\n\tresult,\n\thasNavigated,\n\thasThrownError,\n}: {\n\tisIdle: boolean;\n\tisExecuting: boolean;\n\tisTransitioning: boolean;\n\thasNavigated: boolean;\n\thasThrownError: boolean;\n\tresult: SafeActionResult<ServerError, S, CVE, Data>;\n}): HookActionStatus => {\n\tif (isIdle) {\n\t\treturn \"idle\";\n\t} else if (isExecuting) {\n\t\treturn \"executing\";\n\t} else if (isTransitioning) {\n\t\treturn \"transitioning\";\n\t} else if (\n\t\thasThrownError ||\n\t\ttypeof result.validationErrors !== \"undefined\" ||\n\t\ttypeof result.serverError !== \"undefined\"\n\t) {\n\t\treturn \"hasErrored\";\n\t} else if (hasNavigated) {\n\t\treturn \"hasNavigated\";\n\t} else {\n\t\treturn \"hasSucceeded\";\n\t}\n};\n\nexport const getActionShorthandStatusObject = (status: HookActionStatus): HookShorthandStatus => {\n\treturn {\n\t\tisIdle: status === \"idle\",\n\t\tisExecuting: status === \"executing\",\n\t\tisTransitioning: status === \"transitioning\",\n\t\tisPending: status === \"executing\" || status === \"transitioning\",\n\t\thasSucceeded: status === \"hasSucceeded\",\n\t\thasErrored: status === \"hasErrored\",\n\t\thasNavigated: status === \"hasNavigated\",\n\t};\n};\n\n/**\n * Converts a callback to a ref to avoid triggering re-renders when passed as a\n * prop or avoid re-executing effects when passed as a dependency\n */\nfunction useCallbackRef<T extends (arg: any) => any>(callback: T | undefined): T {\n\tconst callbackRef = React.useRef(callback);\n\tReact.useEffect(() => {\n\t\tcallbackRef.current = callback;\n\t});\n\treturn React.useMemo(() => ((arg) => callbackRef.current?.(arg) as T) as T, []);\n}\n\nexport const useActionCallbacks = <ServerError, S extends StandardSchemaV1 | undefined, CVE, Data>({\n\tresult,\n\tinput,\n\tstatus,\n\tcb,\n\tnavigationError,\n\tthrownError,\n}: {\n\tresult: SafeActionResult<ServerError, S, CVE, Data>;\n\tinput: InferInputOrDefault<S, undefined>;\n\tstatus: HookActionStatus;\n\tcb?: HookCallbacks<ServerError, S, CVE, Data>;\n\tnavigationError: Error | null;\n\tthrownError: Error | null;\n}) => {\n\tconst onExecute = useCallbackRef(cb?.onExecute);\n\tconst onSuccess = useCallbackRef(cb?.onSuccess);\n\tconst onError = useCallbackRef(cb?.onError);\n\tconst onSettled = useCallbackRef(cb?.onSettled);\n\tconst onNavigation = useCallbackRef(cb?.onNavigation);\n\n\t// Execute hook callbacks as non-visual side effects.\n\tReact.useEffect(() => {\n\t\tconst executeCallbacks = async () => {\n\t\t\tswitch (status) {\n\t\t\t\tcase \"executing\":\n\t\t\t\t\tawait Promise.resolve(onExecute?.({ input })).then(() => {});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"transitioning\":\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"hasSucceeded\":\n\t\t\t\t\tif (navigationError || thrownError) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tawait Promise.all([\n\t\t\t\t\t\tPromise.resolve(onSuccess?.({ data: result.data!, input })),\n\t\t\t\t\t\tPromise.resolve(onSettled?.({ result, input })),\n\t\t\t\t\t]);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"hasErrored\":\n\t\t\t\t\tawait Promise.all([\n\t\t\t\t\t\tPromise.resolve(\n\t\t\t\t\t\t\tonError?.({\n\t\t\t\t\t\t\t\terror: { ...result, ...(thrownError ? { thrownError } : {}) },\n\t\t\t\t\t\t\t\tinput,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t),\n\t\t\t\t\t\tPromise.resolve(onSettled?.({ result, input })),\n\t\t\t\t\t]);\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Navigation flow.\n\t\t\t// If the user redirected to a different page, the `hasNavigated` status never gets set.\n\t\t\t// In all the other cases, the `hasNavigated` status is set.\n\t\t\tif (!navigationError) return;\n\t\t\tconst navigationKind = FrameworkErrorHandler.getNavigationKind(navigationError);\n\n\t\t\tif (navigationKind === \"redirect\" || status === \"hasNavigated\") {\n\t\t\t\tconst navigationKind = FrameworkErrorHandler.getNavigationKind(navigationError);\n\t\t\t\tawait Promise.all([\n\t\t\t\t\tPromise.resolve(\n\t\t\t\t\t\tonNavigation?.({\n\t\t\t\t\t\t\tinput,\n\t\t\t\t\t\t\tnavigationKind,\n\t\t\t\t\t\t})\n\t\t\t\t\t),\n\t\t\t\t\tPromise.resolve(onSettled?.({ result, input, navigationKind })),\n\t\t\t\t]);\n\t\t\t}\n\t\t};\n\n\t\texecuteCallbacks().catch(console.error);\n\t}, [input, status, result, navigationError, thrownError, onExecute, onSuccess, onSettled, onError, onNavigation]);\n};\n"],"mappings":";;;;AAMA,MAAa,mBAAmF,EAC/F,QACA,aACA,iBACA,QACA,cACA,qBAQuB;AACvB,KAAI,OACH,QAAO;UACG,YACV,QAAO;UACG,gBACV,QAAO;UAEP,kBACA,OAAO,OAAO,qBAAqB,eACnC,OAAO,OAAO,gBAAgB,YAE9B,QAAO;UACG,aACV,QAAO;KAEP,QAAO;;AAIT,MAAa,kCAAkC,WAAkD;AAChG,QAAO;EACN,QAAQ,WAAW;EACnB,aAAa,WAAW;EACxB,iBAAiB,WAAW;EAC5B,WAAW,WAAW,eAAe,WAAW;EAChD,cAAc,WAAW;EACzB,YAAY,WAAW;EACvB,cAAc,WAAW;EACzB;;;;;;AAOF,SAAS,eAA4C,UAA4B;CAChF,MAAM,cAAc,MAAM,OAAO,SAAS;AAC1C,OAAM,gBAAgB;AACrB,cAAY,UAAU;GACrB;AACF,QAAO,MAAM,gBAAgB,QAAQ,YAAY,UAAU,IAAI,GAAa,EAAE,CAAC;;AAGhF,MAAa,sBAAsF,EAClG,QACA,OACA,QACA,IACA,iBACA,kBAQK;CACL,MAAM,YAAY,eAAe,IAAI,UAAU;CAC/C,MAAM,YAAY,eAAe,IAAI,UAAU;CAC/C,MAAM,UAAU,eAAe,IAAI,QAAQ;CAC3C,MAAM,YAAY,eAAe,IAAI,UAAU;CAC/C,MAAM,eAAe,eAAe,IAAI,aAAa;AAGrD,OAAM,gBAAgB;EACrB,MAAM,mBAAmB,YAAY;AACpC,WAAQ,QAAR;IACC,KAAK;AACJ,WAAM,QAAQ,QAAQ,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC,WAAW,GAAG;AAC5D;IACD,KAAK,gBACJ;IACD,KAAK;AACJ,SAAI,mBAAmB,YACtB;AAGD,WAAM,QAAQ,IAAI,CACjB,QAAQ,QAAQ,YAAY;MAAE,MAAM,OAAO;MAAO;MAAO,CAAC,CAAC,EAC3D,QAAQ,QAAQ,YAAY;MAAE;MAAQ;MAAO,CAAC,CAAC,CAC/C,CAAC;AACF;IACD,KAAK;AACJ,WAAM,QAAQ,IAAI,CACjB,QAAQ,QACP,UAAU;MACT,OAAO;OAAE,GAAG;OAAQ,GAAI,cAAc,EAAE,aAAa,GAAG,EAAE;OAAG;MAC7D;MACA,CAAC,CACF,EACD,QAAQ,QAAQ,YAAY;MAAE;MAAQ;MAAO,CAAC,CAAC,CAC/C,CAAC;AACF;;AAMF,OAAI,CAAC,gBAAiB;AAGtB,OAFuB,sBAAsB,kBAAkB,gBAAgB,KAExD,cAAc,WAAW,gBAAgB;IAC/D,MAAM,iBAAiB,sBAAsB,kBAAkB,gBAAgB;AAC/E,UAAM,QAAQ,IAAI,CACjB,QAAQ,QACP,eAAe;KACd;KACA;KACA,CAAC,CACF,EACD,QAAQ,QAAQ,YAAY;KAAE;KAAQ;KAAO;KAAgB,CAAC,CAAC,CAC/D,CAAC;;;AAIJ,oBAAkB,CAAC,MAAM,QAAQ,MAAM;IACrC;EAAC;EAAO;EAAQ;EAAQ;EAAiB;EAAa;EAAW;EAAW;EAAW;EAAS;EAAa,CAAC"}