server-act
Advanced tools
Comparing version 1.1.7 to 1.2.0
@@ -10,4 +10,4 @@ import { z } from 'zod'; | ||
type SanitizeFunctionParam<T extends (param: any) => any> = T extends (param: infer P) => infer R ? Equals<P, undefined> extends true ? () => R : Equals<P, P | undefined> extends true ? (param?: P) => R : (param: P) => R : never; | ||
type InferParserType<T, TType extends 'in' | 'out'> = T extends z.ZodEffects<infer I, any, any> ? I[TType extends 'in' ? '_input' : '_output'] : T extends z.ZodType ? T[TType extends 'in' ? '_input' : '_output'] : never; | ||
type InferInputType<T, TType extends 'in' | 'out'> = T extends UnsetMarker ? undefined : InferParserType<T, TType>; | ||
type InferParserType<T, TType extends "in" | "out"> = T extends z.ZodEffects<infer I, any, any> ? I[TType extends "in" ? "_input" : "_output"] : T extends z.ZodType ? T[TType extends "in" ? "_input" : "_output"] : never; | ||
type InferInputType<T, TType extends "in" | "out"> = T extends UnsetMarker ? undefined : InferParserType<T, TType>; | ||
type InferContextType<T> = T extends UnsetMarker ? undefined : T; | ||
@@ -23,3 +23,3 @@ interface ActionParams<TInput = unknown, TContext = unknown> { | ||
middleware: <TContext>(middleware: () => Promise<TContext> | TContext) => ActionBuilder<{ | ||
_input: TParams['_input']; | ||
_input: TParams["_input"]; | ||
_context: TContext; | ||
@@ -32,3 +32,3 @@ }>; | ||
_input: TParser; | ||
_context: TParams['_context']; | ||
_context: TParams["_context"]; | ||
}>; | ||
@@ -39,18 +39,19 @@ /** | ||
action: <TOutput>(action: (params: { | ||
ctx: InferContextType<TParams['_context']>; | ||
input: InferInputType<TParams['_input'], 'out'>; | ||
}) => Promise<TOutput>) => SanitizeFunctionParam<(input: InferInputType<TParams['_input'], 'in'>) => Promise<TOutput>>; | ||
ctx: InferContextType<TParams["_context"]>; | ||
input: InferInputType<TParams["_input"], "out">; | ||
}) => Promise<TOutput>) => SanitizeFunctionParam<(input: InferInputType<TParams["_input"], "in">) => Promise<TOutput>>; | ||
/** | ||
* Create an action for React `useFormState` | ||
*/ | ||
formAction: <TState>(action: (params: Prettify<{ | ||
ctx: InferContextType<TParams['_context']>; | ||
formAction: <TState, TPrevState = undefined>(action: (params: Prettify<{ | ||
ctx: InferContextType<TParams["_context"]>; | ||
prevState: any; | ||
formData: FormData; | ||
} & ({ | ||
input: InferInputType<TParams['_input'], 'out'>; | ||
input: InferInputType<TParams["_input"], "out">; | ||
formErrors?: undefined; | ||
} | { | ||
input?: undefined; | ||
formErrors: z.ZodError<InferInputType<TParams['_input'], 'in'>>; | ||
})>) => Promise<TState>) => (prevState: TState, formData: FormData) => Promise<TState>; | ||
formErrors: z.ZodError<InferInputType<TParams["_input"], "in">>; | ||
})>) => Promise<TState>) => (prevState: TState | TPrevState, formData: FormData) => Promise<TState | TPrevState>; | ||
} | ||
@@ -57,0 +58,0 @@ /** |
@@ -68,4 +68,4 @@ Object.defineProperty(exports, '__esModule', { value: true }); | ||
if (!result.success) { | ||
console.error('❌ Input validation error:', result.error.errors); | ||
throw new Error('Input validation error'); | ||
console.error("❌ Input validation error:", result.error.errors); | ||
throw new Error("Input validation error"); | ||
} | ||
@@ -88,2 +88,3 @@ } | ||
prevState, | ||
formData, | ||
formErrors: result.error | ||
@@ -95,2 +96,3 @@ }); | ||
prevState, | ||
formData, | ||
input: result.data | ||
@@ -102,2 +104,3 @@ }); | ||
prevState, | ||
formData, | ||
input: undefined | ||
@@ -104,0 +107,0 @@ }); |
{ | ||
"name": "server-act", | ||
"version": "1.1.7", | ||
"version": "1.2.0", | ||
"homepage": "https://github.com/chungweileong94/server-act#readme", | ||
@@ -47,4 +47,4 @@ "author": "chungweileong94", | ||
"devDependencies": { | ||
"bunchee": "^4.3.3", | ||
"typescript": "^5.2.2", | ||
"bunchee": "^5.1.2", | ||
"typescript": "^5.4.5", | ||
"zod": "^3.22.2", | ||
@@ -54,3 +54,3 @@ "zod-form-data": "^2.0.2" | ||
"peerDependencies": { | ||
"typescript": "^5.2.2", | ||
"typescript": ">=5.0.0", | ||
"zod": "^3.22.2" | ||
@@ -57,0 +57,0 @@ }, |
@@ -24,6 +24,6 @@ # Server-Act | ||
// action.ts | ||
'use server'; | ||
"use server"; | ||
import {serverAct} from 'server-act'; | ||
import {z} from 'zod'; | ||
import { serverAct } from "server-act"; | ||
import { z } from "zod"; | ||
@@ -36,3 +36,3 @@ export const sayHelloAction = serverAct | ||
) | ||
.action(async ({input}) => { | ||
.action(async ({ input }) => { | ||
return `Hello, ${input.name}`; | ||
@@ -44,9 +44,9 @@ }); | ||
// client-component.tsx | ||
'use client'; | ||
"use client"; | ||
import {sayHelloAction} from './action'; | ||
import { sayHelloAction } from "./action"; | ||
export const ClientComponent = () => { | ||
const onClick = () => { | ||
const message = await sayHelloAction({name: 'John'}); | ||
const message = await sayHelloAction({ name: "John" }); | ||
console.log(message); // Hello, John | ||
@@ -67,11 +67,11 @@ }; | ||
// action.ts | ||
'use server'; | ||
"use server"; | ||
import {serverAct} from 'server-act'; | ||
import {z} from 'zod'; | ||
import { serverAct } from "server-act"; | ||
import { z } from "zod"; | ||
export const sayHelloAction = serverAct | ||
.middleware(() => { | ||
const userId = '...'; | ||
return {userId}; | ||
const userId = "..."; | ||
return { userId }; | ||
}) | ||
@@ -83,4 +83,4 @@ .input( | ||
) | ||
.action(async ({ctx, input}) => { | ||
console.log('User ID', ctx.userId); | ||
.action(async ({ ctx, input }) => { | ||
console.log("User ID", ctx.userId); | ||
return `Hello, ${input.name}`; | ||
@@ -90,8 +90,7 @@ }); | ||
### `useFormState` Support | ||
### `useActionState` Support | ||
> `useFormState` Documentation: | ||
> `useActionState` Documentation: | ||
> | ||
> - https://nextjs.org/docs/app/building-your-application/data-fetching/forms-and-mutations#error-handling | ||
> - https://react.dev/reference/react-dom/hooks/useFormState | ||
> - https://react.dev/reference/react/useActionState | ||
@@ -102,7 +101,7 @@ We recommend using [zod-form-data](https://www.npmjs.com/package/zod-form-data) for input validation. | ||
// action.ts; | ||
'use server'; | ||
"use server"; | ||
import {serverAct} from 'server-act'; | ||
import {z} from 'zod'; | ||
import {zfd} from 'zod-form-data'; | ||
import { serverAct } from "server-act"; | ||
import { z } from "zod"; | ||
import { zfd } from "zod-form-data"; | ||
@@ -114,12 +113,12 @@ export const sayHelloAction = serverAct | ||
z | ||
.string({required_error: `You haven't told me your name`}) | ||
.nonempty({message: 'You need to tell me your name!'}), | ||
.string({ required_error: `You haven't told me your name` }) | ||
.max(20, { message: "Any shorter name? You name is too long 😬" }), | ||
), | ||
}), | ||
) | ||
.formAction(async ({input, formErrors, ctx}) => { | ||
.formAction(async ({ formData, input, formErrors, ctx }) => { | ||
if (formErrors) { | ||
return {formErrors: formErrors.formErrors.fieldErrors}; | ||
return { formData, formErrors: formErrors.formErrors.fieldErrors }; | ||
} | ||
return {message: `Hello, ${input.name}!`}; | ||
return { message: `Hello, ${input.name}!` }; | ||
}); | ||
@@ -130,17 +129,22 @@ ``` | ||
// client-component.tsx | ||
'use client'; | ||
"use client"; | ||
import {sayHelloAction} from './action'; | ||
import { useActionState } from "react"; | ||
import { sayHelloAction } from "./action"; | ||
export const ClientComponent = () => { | ||
const [state, dispatch] = useFormState(sayHelloAction, {formErrors: {}}); | ||
const [state, dispatch] = useFormState(sayHelloAction, undefined); | ||
return ( | ||
<form action={dispatch}> | ||
<input name="name" required /> | ||
{state.formErrors?.name?.map((error) => <p key={error}>{error}</p>)} | ||
<input | ||
name="name" | ||
required | ||
defaultValue={state?.formData?.get("name")?.toString()} | ||
/> | ||
{state?.formErrors?.name?.map((error) => <p key={error}>{error}</p>)} | ||
<button type="submit">Submit</button> | ||
{!!state.message && <p>{state.message}</p>} | ||
{!!state?.message && <p>{state.message}</p>} | ||
</form> | ||
@@ -147,0 +151,0 @@ ); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
18004
279
145