react-form-action 2.4.0 → 2.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,6 +8,7 @@ End-to-end typesafe success, error & validation state control for Next.js form a
8
8
 
9
9
  - ✅ Provides envelope objects with `"initial" | "invalid" | "success" | "failure"` response types.
10
10
  - ✅ Define generic payload for each of the response type.
11
+ - ✅ Bind action arguments.
11
12
 
12
13
  **tRPC-like Form Action builder**
13
14
 
@@ -250,6 +251,45 @@ export const updateUser = createFormAction<
250
251
  );
251
252
  ```
252
253
 
254
+ The action creator supports arguments binding:
255
+
256
+ ```ts
257
+ export const updateUser = createFormAction(
258
+ (
259
+ { success, failure, invalid },
260
+ userId: string /* Here you can specify multiple arguments */
261
+ ) =>
262
+ async (prevState, formData) => {
263
+ try {
264
+ const { name } = updateUserSchema.parse({
265
+ name: formData.get("name"),
266
+ });
267
+
268
+ const user = await db.users.findById(userId);
269
+
270
+ if (!user) {
271
+ return failure({ message: "No such user." });
272
+ }
273
+
274
+ const updated = await user.update({ name });
275
+
276
+ if (updated) {
277
+ return success({
278
+ message: "User has been updated.",
279
+ });
280
+ } else {
281
+ return failure({ message: "Failed to update." });
282
+ }
283
+ } catch (error) {
284
+ // handle error
285
+ }
286
+ }
287
+ );
288
+
289
+ // call bind as usuall, the "123" becomes the "userId"
290
+ updateUser.bind(null, "123");
291
+ ```
292
+
253
293
  ### Action Context
254
294
 
255
295
  The `<Action>` components enables you to access your `action`'s state with the `useActionContext()` hook:
@@ -0,0 +1 @@
1
+ function u(a){return{type:"initial",data:a,error:null,validationError:null}}function d(a){function t(r){return{type:"success",data:r,error:null,validationError:null}}function o(r){return{type:"failure",data:null,error:r,validationError:null}}function n(r){return{type:"invalid",data:null,error:null,validationError:r}}return(...r)=>{let e=r.pop(),i=r.pop(),l=[...r];return a({success:t,failure:o,invalid:n},...l)(i,e)}}export{u as a,d as b};
package/dist/client.d.mts CHANGED
@@ -1,9 +1,8 @@
1
1
  import * as React from 'react';
2
2
  import React__default, { PropsWithChildren, JSX } from 'react';
3
- import { F as FormAction, A as ActionState, I as InitialState, a as InvalidState, b as FailureState, S as SuccessState } from './createFormAction-CX4Fk5xA.mjs';
3
+ import { F as FormAction, A as ActionState, I as InitialState, a as InvalidState, b as FailureState, S as SuccessState } from './createFormAction-DjhozgiG.mjs';
4
4
  import { ZodFormattedError } from 'zod';
5
5
  import { RenderProp, RP } from 'react-render-prop-type';
6
- import { useFormStatus } from 'react-dom';
7
6
 
8
7
  type ActionProps<Data, Error, ValidationError> = PropsWithChildren<{
9
8
  action: FormAction<Data, Error, ValidationError>;
@@ -79,8 +78,6 @@ declare function createComponents<Data, Error, ValidationError extends ZodFormat
79
78
  }>) => React__default.ReactNode;
80
79
  };
81
80
 
82
- declare function FormStatus({ children, }: RenderProp<ReturnType<typeof useFormStatus>>): React.ReactNode;
83
-
84
81
  /**
85
82
  * Conditionally renders the children, when the form action is in the "pending" state.
86
83
  */
@@ -88,4 +85,4 @@ declare function Pending({ children, }: PropsWithChildren | RP<{
88
85
  isPending: boolean;
89
86
  }>): React.ReactNode;
90
87
 
91
- export { Action, type ActionContextState, type ActionProps, Form, type FormProps, FormStatus, type InferZodErrorPaths, type Paths, Pending, ZodFieldError, type ZodFieldErrorChildrenProps, type ZodFieldErrorProps, createComponents, noError, useActionContext };
88
+ export { Action, type ActionContextState, type ActionProps, Form, type FormProps, type InferZodErrorPaths, type Paths, Pending, ZodFieldError, type ZodFieldErrorChildrenProps, type ZodFieldErrorProps, createComponents, noError, useActionContext };
package/dist/client.mjs CHANGED
@@ -1 +1 @@
1
- "use client";import{a as m}from"./chunk-HL47DG4L.mjs";import y from"react";import{createContext as P,use as S}from"react";import{useActionState as F}from"react";var p={isInitial:!1,isInvalid:!1,isFailure:!1,isSuccess:!1},u=P(null);function a(t){let o=S(u);if(!o)throw new Error("ActionContext must be initialized before use. Is your useActionContext hook wrapped with an <Action> Component?");return o}function w({children:t,action:o,initialData:i,permalink:e}){let[r,n,s]=F(o,m(i),e),l=r.type==="initial"?{...r,...p,action:n,isPending:s,isInitial:!0}:r.type==="invalid"?{...r,...p,action:n,isPending:s,isInvalid:!0}:r.type==="failure"?{...r,...p,action:n,isPending:s,isFailure:!0}:{...r,...p,action:n,isPending:s,isSuccess:!0};return y.createElement(u,{value:l},t)}import A,{startTransition as C}from"react";function V({autoReset:t=!1,...o}){let{action:i}=a();return A.createElement("form",{...t?{action:i}:{onSubmit:r=>{r.preventDefault();let n=r.currentTarget;C(()=>{i(new FormData(n))})}},...o})}import c from"react";import f from"react";var h=".",d=Object.freeze({_errors:Object.freeze([])});function E({errors:t,name:o,children:i=({error:e})=>f.createElement(f.Fragment,null,e)}){if(o.length===0)return i({name:o,error:t._errors[0],errors:t._errors});let e=o.split(h),r=t;for(;e.length;){let n=e.shift();r=r[n]??d}return i({name:o,error:r._errors[0],errors:r._errors})}function J(t){function o({name:e,children:r}){let{isInvalid:n,validationError:s}=a(t);return c.createElement(E,{errors:s??d,name:e},r??(({error:x})=>n&&c.createElement(c.Fragment,null,x)))}function i({children:e}){let{isSuccess:r,data:n}=a(t);return typeof e=="function"?e(r?{isSuccess:r,data:n}:{isSuccess:r,data:n}):r&&e}return{FieldError:o,Success:i}}import{useFormStatus as k}from"react-dom";function H({children:t}){return t(k())}function B({children:t}){let{isPending:o}=a();return typeof t=="function"?t({isPending:o}):o&&t}export{w as Action,V as Form,H as FormStatus,B as Pending,E as ZodFieldError,J as createComponents,d as noError,a as useActionContext};
1
+ "use client";import{a as m}from"./chunk-LPB4R2UB.mjs";import y from"react";import{createContext as P,use as S}from"react";import{useActionState as F}from"react";var p={isInitial:!1,isInvalid:!1,isFailure:!1,isSuccess:!1},u=P(null);function a(o){let t=S(u);if(!t)throw new Error("ActionContext must be initialized before use. Is your useActionContext hook wrapped with an <Action> Component?");return t}function I({children:o,action:t,initialData:i,permalink:e}){let[r,n,s]=F(t,m(i),e),l=r.type==="initial"?{...r,...p,action:n,isPending:s,isInitial:!0}:r.type==="invalid"?{...r,...p,action:n,isPending:s,isInvalid:!0}:r.type==="failure"?{...r,...p,action:n,isPending:s,isFailure:!0}:{...r,...p,action:n,isPending:s,isSuccess:!0};return y.createElement(u,{value:l},o)}import A,{startTransition as C}from"react";function V({autoReset:o=!1,...t}){let{action:i}=a();return A.createElement("form",{...o?{action:i}:{onSubmit:r=>{r.preventDefault();let n=r.currentTarget;C(()=>{i(new FormData(n))})}},...t})}import c from"react";import f from"react";var h=".",d=Object.freeze({_errors:Object.freeze([])});function E({errors:o,name:t,children:i=({error:e})=>f.createElement(f.Fragment,null,e)}){if(t.length===0)return i({name:t,error:o._errors[0],errors:o._errors});let e=t.split(h),r=o;for(;e.length;){let n=e.shift();r=r[n]??d}return i({name:t,error:r._errors[0],errors:r._errors})}function $(o){function t({name:e,children:r}){let{isInvalid:n,validationError:s}=a(o);return c.createElement(E,{errors:s??d,name:e},r??(({error:x})=>n&&c.createElement(c.Fragment,null,x)))}function i({children:e}){let{isSuccess:r,data:n}=a(o);return typeof e=="function"?e(r?{isSuccess:r,data:n}:{isSuccess:r,data:n}):r&&e}return{FieldError:t,Success:i}}function X({children:o}){let{isPending:t}=a();return typeof o=="function"?o({isPending:t}):t&&o}export{I as Action,V as Form,X as Pending,E as ZodFieldError,$ as createComponents,d as noError,a as useActionContext};
@@ -23,12 +23,16 @@ type SuccessState<T> = {
23
23
  validationError: null;
24
24
  };
25
25
  type ActionState<Data, Error, ValidationError = Record<string, never>> = InitialState<Data> | InvalidState<ValidationError> | FailureState<Error> | SuccessState<Data>;
26
- type FormAction<Data, Error = Data, ValidationError = Record<string, never>, Payload = FormData> = (state: ActionState<Data, Error, ValidationError>, payload: Payload) => Promise<ActionState<Data, Error, ValidationError>>;
26
+ type FormAction<Data, Error = Data, ValidationError = Record<string, never>, Payload = FormData, Arguments extends unknown[] = []> = (...args: [
27
+ ...Arguments,
28
+ state: ActionState<Data, Error, ValidationError>,
29
+ payload: Payload
30
+ ]) => Promise<ActionState<Data, Error, ValidationError>>;
27
31
  declare function initial<Data>(data: Data): InitialState<Data>;
28
- declare function createFormAction<Data, Error = Data, ValidationError = Record<string, never>, Payload = FormData>(formAction: (params: {
32
+ declare function createFormAction<Data, Error = Data, ValidationError = Record<string, never>, Payload = FormData, Arguments extends [...unknown[]] = []>(formAction: (params: {
29
33
  success: (data: Data) => SuccessState<Data>;
30
34
  failure: (error: Error) => FailureState<Error>;
31
35
  invalid: (validationError: ValidationError) => InvalidState<ValidationError>;
32
- }) => FormAction<Data, Error, ValidationError, Payload>): (state: ActionState<Data, Error, ValidationError>, payload: Payload) => Promise<ActionState<Data, Error, ValidationError>>;
36
+ }, ...args: Arguments) => FormAction<Data, Error, ValidationError, Payload>): (...args: [...Arguments, state: ActionState<Data, Error, ValidationError>, payload: Payload]) => Promise<ActionState<Data, Error, ValidationError>>;
33
37
 
34
38
  export { type ActionState as A, type FormAction as F, type InitialState as I, type SuccessState as S, type InvalidState as a, type FailureState as b, createFormAction as c, initial as i };
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as ActionState, a as InvalidState, b as FailureState, S as SuccessState } from './createFormAction-CX4Fk5xA.mjs';
2
- export { F as FormAction, I as InitialState, c as createFormAction, i as initial } from './createFormAction-CX4Fk5xA.mjs';
1
+ import { A as ActionState, a as InvalidState, b as FailureState, S as SuccessState } from './createFormAction-DjhozgiG.mjs';
2
+ export { F as FormAction, I as InitialState, c as createFormAction, i as initial } from './createFormAction-DjhozgiG.mjs';
3
3
  import { ZodTypeAny, ZodType, ZodObject, ZodRawShape, objectUtil, z, ZodSchema, ZodEffects } from 'zod';
4
4
 
5
5
  declare const emptyInput: unique symbol;
@@ -34,7 +34,7 @@ type FormActionBuilder<Schema extends ZodTypeAny | EmptyInput, Err = Error, Cont
34
34
  * @param action async function to execute. It will receive parsed formData as input, when the builder was initialized with a schema.
35
35
  * @returns runnable server action exportable from a module.
36
36
  */
37
- run: Schema extends ZodTypeAny ? <Data>(action: SchemaAction<Data, Context, Schema>) => (state: ActionState<Data, Err, z.inferFormattedError<Schema>>, payload: FormData) => Promise<Flatten<InvalidState<z.inferFormattedError<Schema>> | FailureState<Err> | SuccessState<Data>>> : <Data>(action: Action<Data, Context>) => (state: ActionState<Data, Err>, payload: FormData) => Promise<Flatten<FailureState<Err> | SuccessState<Data>>>;
37
+ run: Schema extends ZodTypeAny ? <Data>(action: SchemaAction<Data, Flatten<Context>, Schema>) => (state: ActionState<Data, Err, z.inferFormattedError<Schema>>, payload: FormData) => Promise<Flatten<InvalidState<z.inferFormattedError<Schema>> | FailureState<Err> | SuccessState<Data>>> : <Data>(action: Action<Data, Flatten<Context>>) => (state: ActionState<Data, Err>, payload: FormData) => Promise<Flatten<FailureState<Err> | SuccessState<Data>>>;
38
38
  /**
39
39
  * A chainable context enhancing helper.
40
40
  * @param middleware A function which receives the current context, and returns an object which will be added to the context.
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{a as A,b as p}from"./chunk-HL47DG4L.mjs";import{ZodFirstPartyTypeKind as C}from"zod";import{zfd as E}from"zod-form-data";var d=Symbol();function i(n,o=[],r){async function f(t){let e={formData:t};for(let a of o){let s=await a({ctx:e});e={...e,...s}}return e}return{input(t){if(n===d)return i(t,o,r);if(n._def.effect)throw new Error("Previous input is not augmentable because it contains an effect.");if(t._def.effect)throw new Error("Your input contains effect which prevents merging it with the previous inputs.");if(n._def.typeName===C.ZodObject){let e=n.merge(t);return i(e,o)}else throw Error("Merging inputs works only for object schemas without effects.")},use(t){return i(n,[...o,t],r)},error(t){return i(n,o,t)},run:n===d?t=>p(({success:e,failure:a})=>async(s,x)=>{let m=await f(x);try{return e(await t({ctx:m}))}catch(c){if(r)return a(await r({error:c,ctx:m}));throw c}}):n===d?void 0:t=>p(({success:e,failure:a,invalid:s})=>{let x=E.formData(n);return async(m,c)=>{let y=await f(c),u=x.safeParse(c);if(!u.success)return s(u.error.format());let h=u.data;try{return e(await t({input:h,ctx:y}))}catch(S){if(r)return a(await r({error:S,ctx:y}));throw S}}})}}var N=i(d);export{p as createFormAction,N as formAction,A as initial};
1
+ import{a as A,b as p}from"./chunk-LPB4R2UB.mjs";import{ZodFirstPartyTypeKind as E}from"zod";import{zfd as C}from"zod-form-data";var d=Symbol();function i(r,o=[],n){async function f(t){let e={formData:t};for(let a of o){let s=await a({ctx:e});e={...e,...s}}return e}return{input(t){if(r===d)return i(t,o,n);if(r._def.effect)throw new Error("Previous input is not augmentable because it contains an effect.");if(t._def.effect)throw new Error("Your input contains effect which prevents merging it with the previous inputs.");if(r._def.typeName===E.ZodObject){let e=r.merge(t);return i(e,o)}else throw Error("Merging inputs works only for object schemas without effects.")},use(t){return i(r,[...o,t],n)},error(t){return i(r,o,t)},run:r===d?t=>p(({success:e,failure:a})=>async(s,m)=>{let x=await f(m);try{return e(await t({ctx:x}))}catch(c){if(n)return a(await n({error:c,ctx:x}));throw c}}):r===d?void 0:t=>p(({success:e,failure:a,invalid:s})=>{let m=C.formData(r);return async(x,c)=>{let y=await f(c),u=m.safeParse(c);if(!u.success)return s(u.error.format());let h=u.data;try{return e(await t({input:h,ctx:y}))}catch(S){if(n)return a(await n({error:S,ctx:y}));throw S}}})}}var P=i(d);export{p as createFormAction,P as formAction,A as initial};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-form-action",
3
- "version": "2.4.0",
3
+ "version": "2.4.2",
4
4
  "description": "State management helpers for the react form actions.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1 +0,0 @@
1
- function l(a){return{type:"initial",data:a,error:null,validationError:null}}function n(a){function t(r){return{type:"success",data:r,error:null,validationError:null}}function o(r){return{type:"failure",data:null,error:r,validationError:null}}function i(r){return{type:"invalid",data:null,error:null,validationError:r}}return(r,e)=>a({success:t,failure:o,invalid:i})(r,e)}export{l as a,n as b};