UNPKG

next-safe-action

Version:

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

474 lines (468 loc) 16.4 kB
import { Schema, Infer, InferIn, ValidationAdapter, InferInArray, InferArray } from "./adapters/types.mjs"; type Prettify<T> = { [K in keyof T]: T[K]; } & {}; type MaybePromise<T> = Promise<T> | T; type NotObject = number | string | boolean | bigint | symbol | null | undefined | any[]; type VEList = Prettify<{ _errors?: string[]; }>; type SchemaErrors<S> = { [K in keyof S]?: S[K] extends NotObject ? VEList : Prettify<VEList & SchemaErrors<S[K]>>; } & {}; /** * Type of the returned object when validation fails. */ type ValidationErrors<S extends Schema | undefined> = S extends Schema ? Infer<S> extends NotObject ? VEList : Prettify<VEList & SchemaErrors<Infer<S>>> : undefined; /** * Type of the array of bind arguments validation errors. */ type BindArgsValidationErrors<BAS extends readonly Schema[]> = { [K in keyof BAS]: ValidationErrors<BAS[K]>; }; /** * Type of flattened validation errors. `formErrors` contains global errors, and `fieldErrors` * contains errors for each field, one level deep. */ type FlattenedValidationErrors<VE extends ValidationErrors<any>> = Prettify<{ formErrors: string[]; fieldErrors: { [K in keyof Omit<VE, "_errors">]?: string[]; }; }>; /** * Type of flattened bind arguments validation errors. */ type FlattenedBindArgsValidationErrors<BAVE extends readonly ValidationErrors<any>[]> = { [K in keyof BAVE]: FlattenedValidationErrors<BAVE[K]>; }; /** * Type of the function used to format validation errors. */ type HandleValidationErrorsShapeFn< S extends Schema | undefined, BAS extends readonly Schema[], MD, Ctx extends object, CVE, > = ( validationErrors: ValidationErrors<S>, utils: { clientInput: S extends Schema ? InferIn<S> : undefined; bindArgsClientInputs: BAS; metadata: MD; ctx: Prettify<Ctx>; } ) => Promise<CVE>; /** * Type of the function used to format bind arguments validation errors. */ type HandleBindArgsValidationErrorsShapeFn< S extends Schema | undefined, BAS extends readonly Schema[], MD, Ctx extends object, CBAVE, > = ( bindArgsValidationErrors: BindArgsValidationErrors<BAS>, utils: { clientInput: S extends Schema ? InferIn<S> : undefined; bindArgsClientInputs: BAS; metadata: MD; ctx: Prettify<Ctx>; } ) => Promise<CBAVE>; declare class SafeActionClient< ServerError, ODVES extends DVES | undefined, // override default validation errors shape MetadataSchema extends Schema | undefined = undefined, MD = MetadataSchema extends Schema ? Infer<MetadataSchema> : undefined, // metadata type (inferred from metadata schema) Ctx extends object = {}, ISF extends (() => Promise<Schema>) | undefined = undefined, // input schema function IS extends Schema | undefined = ISF extends Function ? Awaited<ReturnType<ISF>> : undefined, // input schema OS extends Schema | undefined = undefined, // output schema const BAS extends readonly Schema[] = [], CVE = undefined, const CBAVE = undefined, > { #private; constructor( opts: { middlewareFns: MiddlewareFn<ServerError, any, any, any>[]; metadataSchema: MetadataSchema; metadata: MD; inputSchemaFn: ISF; outputSchema: OS; bindArgsSchemas: BAS; validationAdapter: ValidationAdapter; handleValidationErrorsShape: HandleValidationErrorsShapeFn<IS, BAS, MD, Ctx, CVE>; handleBindArgsValidationErrorsShape: HandleBindArgsValidationErrorsShapeFn<IS, BAS, MD, Ctx, CBAVE>; ctxType: Ctx; } & Required< Pick< SafeActionClientOpts<ServerError, MetadataSchema, ODVES>, "handleServerError" | "defaultValidationErrorsShape" | "throwValidationErrors" > > ); /** * Use a middleware function. * @param middlewareFn Middleware function * * {@link https://next-safe-action.dev/docs/define-actions/instance-methods#use See docs for more information} */ use<NextCtx extends object>( middlewareFn: MiddlewareFn<ServerError, MD, Ctx, Ctx & NextCtx> ): SafeActionClient<ServerError, ODVES, MetadataSchema, MD, Ctx & NextCtx, ISF, IS, OS, BAS, CVE, CBAVE>; /** * Define metadata for the action. * @param data Metadata with the same type as the return value of the [`defineMetadataSchema`](https://next-safe-action.dev/docs/define-actions/create-the-client#definemetadataschema) optional initialization function * * {@link https://next-safe-action.dev/docs/define-actions/instance-methods#metadata See docs for more information} */ metadata(data: MD): SafeActionClient<ServerError, ODVES, MetadataSchema, MD, Ctx, ISF, IS, OS, BAS, CVE, CBAVE>; /** * Define the input validation schema for the action. * @param inputSchema Input validation schema * @param utils Optional utils object * * {@link https://next-safe-action.dev/docs/define-actions/create-the-client#inputschema See docs for more information} */ schema< OIS extends Schema | ((prevSchema: IS) => Promise<Schema>), // override input schema AIS extends Schema = OIS extends (prevSchema: IS) => Promise<Schema> ? Awaited<ReturnType<OIS>> : OIS, // actual input schema OCVE = ODVES extends "flattened" ? FlattenedValidationErrors<ValidationErrors<AIS>> : ValidationErrors<AIS>, >( inputSchema: OIS, utils?: { handleValidationErrorsShape?: HandleValidationErrorsShapeFn<AIS, BAS, MD, Ctx, OCVE>; } ): SafeActionClient<ServerError, ODVES, MetadataSchema, MD, Ctx, ISF, AIS, OS, BAS, OCVE, CBAVE>; /** * Define the bind args input validation schema for the action. * @param bindArgsSchemas Bind args input validation schemas * @param utils Optional utils object * * {@link https://next-safe-action.dev/docs/define-actions/instance-methods#bindargsschemas See docs for more information} */ bindArgsSchemas< const OBAS extends readonly Schema[], OCBAVE = ODVES extends "flattened" ? FlattenedBindArgsValidationErrors<BindArgsValidationErrors<OBAS>> : BindArgsValidationErrors<OBAS>, >( bindArgsSchemas: OBAS, utils?: { handleBindArgsValidationErrorsShape?: HandleBindArgsValidationErrorsShapeFn<IS, OBAS, MD, Ctx, OCBAVE>; } ): SafeActionClient<ServerError, ODVES, MetadataSchema, MD, Ctx, ISF, IS, OS, OBAS, CVE, OCBAVE>; /** * Define the output data validation schema for the action. * @param schema Output data validation schema * * {@link https://next-safe-action.dev/docs/define-actions/create-the-client#outputschema See docs for more information} */ outputSchema<OOS extends Schema>( dataSchema: OOS ): SafeActionClient<ServerError, ODVES, MetadataSchema, MD, Ctx, ISF, IS, OOS, BAS, CVE, CBAVE>; /** * Define the action. * @param serverCodeFn Code that will be executed on the **server side** * @param [cb] Optional callbacks that will be called after action execution, on the server. * * {@link https://next-safe-action.dev/docs/define-actions/instance-methods#action--stateaction See docs for more information} */ action<Data extends OS extends Schema ? Infer<OS> : any>( serverCodeFn: ServerCodeFn<MD, Ctx, IS, BAS, Data>, utils?: SafeActionUtils<ServerError, MD, Ctx, IS, BAS, CVE, CBAVE, Data> ): SafeActionFn<ServerError, IS, BAS, CVE, CBAVE, Data>; /** * Define the stateful action. * To be used with the [`useStateAction`](https://next-safe-action.dev/docs/execute-actions/hooks/usestateaction) hook. * @param serverCodeFn Code that will be executed on the **server side** * @param [cb] Optional callbacks that will be called after action execution, on the server. * * {@link https://next-safe-action.dev/docs/define-actions/instance-methods#action--stateaction See docs for more information} */ stateAction<Data extends OS extends Schema ? Infer<OS> : any>( serverCodeFn: StateServerCodeFn<ServerError, MD, Ctx, IS, BAS, CVE, CBAVE, Data>, utils?: SafeActionUtils<ServerError, MD, Ctx, IS, BAS, CVE, CBAVE, Data> ): SafeStateActionFn<ServerError, IS, BAS, CVE, CBAVE, Data>; } /** * Type of the default validation errors shape passed to `createSafeActionClient` via `defaultValidationErrorsShape` * property. */ type DVES = "formatted" | "flattened"; /** * Type of the util properties passed to server error handler functions. */ type ServerErrorFunctionUtils<MetadataSchema extends Schema | undefined> = { clientInput: unknown; bindArgsClientInputs: unknown[]; ctx: object; metadata: MetadataSchema extends Schema ? Infer<MetadataSchema> : undefined; }; /** * Type of options when creating a new safe action client. */ type SafeActionClientOpts<ServerError, MetadataSchema extends Schema | undefined, ODVES extends DVES | undefined> = { validationAdapter?: ValidationAdapter; defineMetadataSchema?: () => MetadataSchema; handleServerError?: (error: Error, utils: ServerErrorFunctionUtils<MetadataSchema>) => MaybePromise<ServerError>; throwValidationErrors?: boolean; defaultValidationErrorsShape?: ODVES; }; /** * Type of the result of a safe action. */ type SafeActionResult< ServerError, S extends Schema | undefined, BAS extends readonly Schema[], CVE = ValidationErrors<S>, CBAVE = BindArgsValidationErrors<BAS>, Data = unknown, NextCtx = object, > = { data?: Data; serverError?: ServerError; validationErrors?: CVE; bindArgsValidationErrors?: CBAVE; }; /** * Type of the function called from components with type safe input data. */ type SafeActionFn<ServerError, S extends Schema | undefined, BAS extends readonly Schema[], CVE, CBAVE, Data> = ( ...clientInputs: [...bindArgsInputs: InferInArray<BAS>, input: S extends Schema ? InferIn<S> : void] ) => Promise<SafeActionResult<ServerError, S, BAS, CVE, CBAVE, Data> | undefined>; /** * Type of the stateful function called from components with type safe input data. */ type SafeStateActionFn<ServerError, S extends Schema | undefined, BAS extends readonly Schema[], CVE, CBAVE, Data> = ( ...clientInputs: [ ...bindArgsInputs: InferInArray<BAS>, prevResult: Prettify<SafeActionResult<ServerError, S, BAS, CVE, CBAVE, Data>>, input: S extends Schema ? InferIn<S> : void, ] ) => Promise<SafeActionResult<ServerError, S, BAS, CVE, CBAVE, Data>>; /** * Type of the result of a middleware function. It extends the result of a safe action with * information about the action execution. */ type MiddlewareResult<ServerError, NextCtx extends object> = SafeActionResult< ServerError, any, any, any, any, any, NextCtx > & { parsedInput?: unknown; bindArgsParsedInputs?: unknown[]; ctx?: object; success: boolean; }; /** * Type of the middleware function passed to a safe action client. */ type MiddlewareFn<ServerError, MD, Ctx extends object, NextCtx extends object> = { (opts: { clientInput: unknown; bindArgsClientInputs: unknown[]; ctx: Prettify<Ctx>; metadata: MD; next: { <NC extends object = {}>(opts?: { ctx?: NC }): Promise<MiddlewareResult<ServerError, NC>>; }; }): Promise<MiddlewareResult<ServerError, NextCtx>>; }; /** * Type of the function that executes server code when defining a new safe action. */ type ServerCodeFn<MD, Ctx extends object, S extends Schema | undefined, BAS extends readonly Schema[], Data> = (args: { parsedInput: S extends Schema ? Infer<S> : undefined; clientInput: S extends Schema ? InferIn<S> : undefined; bindArgsParsedInputs: InferArray<BAS>; bindArgsClientInputs: InferInArray<BAS>; ctx: Prettify<Ctx>; metadata: MD; }) => Promise<Data>; /** * Type of the function that executes server code when defining a new stateful safe action. */ type StateServerCodeFn< ServerError, MD, Ctx extends object, S extends Schema | undefined, BAS extends readonly Schema[], CVE, CBAVE, Data, > = ( args: { parsedInput: S extends Schema ? Infer<S> : undefined; clientInput: S extends Schema ? InferIn<S> : undefined; bindArgsParsedInputs: InferArray<BAS>; bindArgsClientInputs: InferInArray<BAS>; ctx: Prettify<Ctx>; metadata: MD; }, utils: { prevResult: Prettify<SafeActionResult<ServerError, S, BAS, CVE, CBAVE, Data>>; } ) => Promise<Data>; /** * Type of action execution utils. It includes action callbacks and other utils. */ type SafeActionUtils< ServerError, MD, Ctx extends object, S extends Schema | undefined, BAS extends readonly Schema[], CVE, CBAVE, Data, > = { throwServerError?: boolean; throwValidationErrors?: boolean; onSuccess?: (args: { data?: Data; metadata: MD; ctx?: Prettify<Ctx>; clientInput: S extends Schema ? InferIn<S> : undefined; bindArgsClientInputs: InferInArray<BAS>; parsedInput: S extends Schema ? Infer<S> : undefined; bindArgsParsedInputs: InferArray<BAS>; hasRedirected: boolean; hasNotFound: boolean; hasForbidden: boolean; hasUnauthorized: boolean; }) => Promise<unknown>; onError?: (args: { error: Prettify<Omit<SafeActionResult<ServerError, S, BAS, CVE, CBAVE, Data>, "data">>; metadata: MD; ctx?: Prettify<Ctx>; clientInput: S extends Schema ? InferIn<S> : undefined; bindArgsClientInputs: InferInArray<BAS>; }) => Promise<unknown>; onSettled?: (args: { result: Prettify<SafeActionResult<ServerError, S, BAS, CVE, CBAVE, Data>>; metadata: MD; ctx?: Prettify<Ctx>; clientInput: S extends Schema ? InferIn<S> : undefined; bindArgsClientInputs: InferInArray<BAS>; hasRedirected: boolean; hasNotFound: boolean; hasForbidden: boolean; hasUnauthorized: boolean; }) => Promise<unknown>; }; /** * Infer input types of a safe action. */ type InferSafeActionFnInput<T extends Function> = T extends | SafeActionFn<any, infer S extends Schema | undefined, infer BAS extends readonly Schema[], any, any, any> | SafeStateActionFn<any, infer S extends Schema | undefined, infer BAS extends readonly Schema[], any, any, any> ? S extends Schema ? { clientInput: InferIn<S>; bindArgsClientInputs: InferInArray<BAS>; parsedInput: Infer<S>; bindArgsParsedInputs: InferArray<BAS>; } : { clientInput: undefined; bindArgsClientInputs: InferInArray<BAS>; parsedInput: undefined; bindArgsParsedInputs: InferArray<BAS>; } : never; /** * Infer the result type of a safe action. */ type InferSafeActionFnResult<T extends Function> = T extends | SafeActionFn< infer ServerError, infer S extends Schema | undefined, infer BAS extends readonly Schema[], infer CVE, infer CBAVE, infer Data > | SafeStateActionFn< infer ServerError, infer S extends Schema | undefined, infer BAS extends readonly Schema[], infer CVE, infer CBAVE, infer Data > ? SafeActionResult<ServerError, S, BAS, CVE, CBAVE, Data> : never; /** * Infer the next context type returned by a middleware function using the `next` function. */ type InferMiddlewareFnNextCtx<T> = T extends MiddlewareFn<any, any, any, infer NextCtx extends object> ? NextCtx : never; /** * Infer the context type of a safe action client or middleware function. */ type InferCtx<T> = T extends | SafeActionClient<any, any, any, any, infer Ctx extends object, any, any, any, any, any> | MiddlewareFn<any, any, infer Ctx extends object, any> ? Ctx : never; /** * Infer the metadata type of a safe action client or middleware function. */ type InferMetadata<T> = T extends | SafeActionClient<any, any, any, infer MD, any, any, any, any, any, any> | MiddlewareFn<any, infer MD, any, any> ? MD : never; /** * Infer the server error type from a safe action client or a middleware function or a safe action function. */ type InferServerError<T> = T extends | SafeActionClient<infer ServerError, any, any, any, any, any, any, any, any, any> | MiddlewareFn<infer ServerError, any, any, any> | SafeActionFn<infer ServerError, any, any, any, any, any> | SafeStateActionFn<infer ServerError, any, any, any, any, any> ? ServerError : never; export { type BindArgsValidationErrors as B, type DVES as D, type FlattenedBindArgsValidationErrors as F, type HandleValidationErrorsShapeFn as H, type InferSafeActionFnInput as I, type MiddlewareFn as M, type Prettify as P, type SafeActionClientOpts as S, type ValidationErrors as V, SafeActionClient as a, type ServerErrorFunctionUtils as b, type SafeActionResult as c, type SafeActionFn as d, type SafeStateActionFn as e, type MiddlewareResult as f, type ServerCodeFn as g, type StateServerCodeFn as h, type SafeActionUtils as i, type InferSafeActionFnResult as j, type InferMiddlewareFnNextCtx as k, type InferCtx as l, type InferMetadata as m, type InferServerError as n, type FlattenedValidationErrors as o, type HandleBindArgsValidationErrorsShapeFn as p, type MaybePromise as q, };