UNPKG

next-safe-action

Version:

Type safe and validated Server Actions in your Next.js project.

1 lines 9.21 kB
{"version":3,"sources":["../src/stateful-hooks.ts","../src/hooks-utils.ts"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport {} from \"react/experimental\";\nimport type {} from \"zod\";\nimport type { InferIn, Schema } from \"./adapters/types\";\nimport { getActionShorthandStatusObject, getActionStatus, useActionCallbacks, useExecuteOnMount } from \"./hooks-utils\";\nimport type { HookBaseUtils, HookCallbacks, HookSafeStateActionFn, UseStateActionHookReturn } from \"./hooks.types\";\n/**\n * Use the stateful action from a Client Component via hook. Used for actions defined with [`stateAction`](https://next-safe-action.dev/docs/define-actions/instance-methods#action--stateaction).\n * @param safeActionFn The action function\n * @param utils Optional `initResult`, `permalink`, base utils and callbacks\n *\n * {@link https://next-safe-action.dev/docs/execute-actions/hooks/usestateaction See docs for more information}\n */\nexport const useStateAction = <\n\tServerError,\n\tS extends Schema | undefined,\n\tconst BAS extends readonly Schema[],\n\tCVE,\n\tCBAVE,\n\tData,\n>(\n\tsafeActionFn: HookSafeStateActionFn<ServerError, S, BAS, CVE, CBAVE, Data>,\n\tutils?: {\n\t\tinitResult?: Awaited<ReturnType<typeof safeActionFn>>;\n\t\tpermalink?: string;\n\t} & HookBaseUtils<S> &\n\t\tHookCallbacks<ServerError, S, BAS, CVE, CBAVE, Data>\n): UseStateActionHookReturn<ServerError, S, BAS, CVE, CBAVE, Data> => {\n\tconst [result, dispatcher, isExecuting] = React.useActionState(\n\t\tsafeActionFn,\n\t\tutils?.initResult ?? {},\n\t\tutils?.permalink\n\t);\n\tconst [isIdle, setIsIdle] = React.useState(true);\n\tconst [isTransitioning, startTransition] = React.useTransition();\n\tconst [clientInput, setClientInput] = React.useState<S extends Schema ? InferIn<S> : void>();\n\tconst status = getActionStatus<ServerError, S, BAS, CVE, CBAVE, Data>({\n\t\tisExecuting,\n\t\tresult: result ?? {},\n\t\tisIdle,\n\t});\n\n\tconst execute = React.useCallback(\n\t\t(input: S extends Schema ? InferIn<S> : void) => {\n\t\t\tsetTimeout(() => {\n\t\t\t\tsetIsIdle(false);\n\t\t\t\tsetClientInput(input);\n\t\t\t}, 0);\n\n\t\t\tstartTransition(() => {\n\t\t\t\tdispatcher(input as S extends Schema ? InferIn<S> : undefined);\n\t\t\t});\n\t\t},\n\t\t[dispatcher]\n\t);\n\n\tuseExecuteOnMount({\n\t\texecuteOnMount: utils?.executeOnMount,\n\t\texecuteFn: execute,\n\t});\n\n\tuseActionCallbacks({\n\t\tresult: result ?? {},\n\t\tinput: clientInput as S extends Schema ? InferIn<S> : undefined,\n\t\tstatus,\n\t\tcb: {\n\t\t\tonExecute: utils?.onExecute,\n\t\t\tonSuccess: utils?.onSuccess,\n\t\t\tonError: utils?.onError,\n\t\t\tonSettled: utils?.onSettled,\n\t\t},\n\t});\n\n\treturn {\n\t\texecute,\n\t\tinput: clientInput as S extends Schema ? InferIn<S> : undefined,\n\t\tresult,\n\t\tstatus,\n\t\t...getActionShorthandStatusObject({ status, isTransitioning }),\n\t};\n};\n","import * as React from \"react\";\nimport {} from \"react/experimental\";\nimport type {} from \"zod\";\nimport type { InferIn, Schema } from \"./adapters/types\";\nimport type { HookActionStatus, HookBaseUtils, HookCallbacks, HookShorthandStatus } from \"./hooks.types\";\nimport type { SafeActionResult } from \"./index.types\";\n\nexport const getActionStatus = <\n\tServerError,\n\tS extends Schema | undefined,\n\tconst BAS extends readonly Schema[],\n\tCVE,\n\tCBAVE,\n\tData,\n>({\n\tisIdle,\n\tisExecuting,\n\tresult,\n}: {\n\tisIdle: boolean;\n\tisExecuting: boolean;\n\tresult: SafeActionResult<ServerError, S, BAS, CVE, CBAVE, Data>;\n}): HookActionStatus => {\n\tif (isIdle) {\n\t\treturn \"idle\";\n\t} else if (isExecuting) {\n\t\treturn \"executing\";\n\t} else if (\n\t\ttypeof result.validationErrors !== \"undefined\" ||\n\t\ttypeof result.bindArgsValidationErrors !== \"undefined\" ||\n\t\ttypeof result.serverError !== \"undefined\"\n\t) {\n\t\treturn \"hasErrored\";\n\t} else {\n\t\treturn \"hasSucceeded\";\n\t}\n};\n\nexport const getActionShorthandStatusObject = ({\n\tstatus,\n\tisTransitioning,\n}: {\n\tstatus: HookActionStatus;\n\tisTransitioning: boolean;\n}): HookShorthandStatus => {\n\treturn {\n\t\tisIdle: status === \"idle\",\n\t\tisExecuting: status === \"executing\",\n\t\tisTransitioning,\n\t\tisPending: status === \"executing\" || isTransitioning,\n\t\thasSucceeded: status === \"hasSucceeded\",\n\t\thasErrored: status === \"hasErrored\",\n\t};\n};\n\nexport const useExecuteOnMount = <S extends Schema | undefined>(\n\targs: HookBaseUtils<S> & {\n\t\texecuteFn: (input: S extends Schema ? InferIn<S> : void) => void;\n\t}\n) => {\n\tconst mounted = React.useRef(false);\n\n\tReact.useEffect(() => {\n\t\tconst t = setTimeout(() => {\n\t\t\tif (args.executeOnMount && !mounted.current) {\n\t\t\t\targs.executeFn(args.executeOnMount.input as S extends Schema ? InferIn<S> : void);\n\t\t\t\tmounted.current = true;\n\t\t\t}\n\t\t}, args.executeOnMount?.delayMs ?? 0);\n\n\t\treturn () => {\n\t\t\tclearTimeout(t);\n\t\t};\n\t}, [args]);\n};\n\nexport const useActionCallbacks = <\n\tServerError,\n\tS extends Schema | undefined,\n\tconst BAS extends readonly Schema[],\n\tCVE,\n\tCBAVE,\n\tData,\n>({\n\tresult,\n\tinput,\n\tstatus,\n\tcb,\n}: {\n\tresult: SafeActionResult<ServerError, S, BAS, CVE, CBAVE, Data>;\n\tinput: S extends Schema ? InferIn<S> : undefined;\n\tstatus: HookActionStatus;\n\tcb?: HookCallbacks<ServerError, S, BAS, CVE, CBAVE, Data>;\n}) => {\n\tconst onExecuteRef = React.useRef(cb?.onExecute);\n\tconst onSuccessRef = React.useRef(cb?.onSuccess);\n\tconst onErrorRef = React.useRef(cb?.onError);\n\tconst onSettledRef = React.useRef(cb?.onSettled);\n\n\t// Execute the callback when the action status changes.\n\tReact.useEffect(() => {\n\t\tconst onExecute = onExecuteRef.current;\n\t\tconst onSuccess = onSuccessRef.current;\n\t\tconst onError = onErrorRef.current;\n\t\tconst onSettled = onSettledRef.current;\n\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 }));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"hasSucceeded\":\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(onError?.({ error: result, 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}\n\t\t};\n\n\t\texecuteCallbacks().catch(console.error);\n\t}, [status, result, input]);\n};\n"],"mappings":"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","names":["React"]}