UNPKG

next-safe-action

Version:

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

579 lines (573 loc) 20.9 kB
/** The Standard Schema interface. */ interface StandardSchemaV1<Input = unknown, Output = Input> { /** The Standard Schema properties. */ readonly "~standard": StandardSchemaV1.Props<Input, Output>; } declare namespace StandardSchemaV1 { /** The Standard Schema properties interface. */ interface Props<Input = unknown, Output = Input> { /** The version number of the standard. */ readonly version: 1; /** The vendor name of the schema library. */ readonly vendor: string; /** Validates unknown input values. */ readonly validate: (value: unknown) => Result<Output> | Promise<Result<Output>>; /** Inferred types associated with the schema. */ readonly types?: Types<Input, Output> | undefined; } /** The result interface of the validate function. */ type Result<Output> = SuccessResult<Output> | FailureResult; /** The result interface if validation succeeds. */ interface SuccessResult<Output> { /** The typed output value. */ readonly value: Output; /** The non-existent issues. */ readonly issues?: undefined; } /** The result interface if validation fails. */ interface FailureResult { /** The issues of failed validation. */ readonly issues: ReadonlyArray<Issue>; } /** The issue interface of the failure output. */ interface Issue { /** The error message of the issue. */ readonly message: string; /** The path of the issue, if any. */ readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined; } /** The path segment interface of the issue. */ interface PathSegment { /** The key representing a path segment. */ readonly key: PropertyKey; } /** The Standard Schema types interface. */ interface Types<Input = unknown, Output = Input> { /** The input type of the schema. */ readonly input: Input; /** The output type of the schema. */ readonly output: Output; } /** Infers the input type of a Standard Schema. */ type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["input"]; /** Infers the output type of a Standard Schema. */ type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["output"]; } /** Infer the input type of an array of Standard Schemas. */ type InferInputArray<Schemas extends readonly StandardSchemaV1[]> = { [K in keyof Schemas]: StandardSchemaV1.InferInput<Schemas[K]>; }; /** Infer the output type of an array of Standard Schemas. */ type InferOutputArray<Schemas extends readonly StandardSchemaV1[]> = { [K in keyof Schemas]: StandardSchemaV1.InferOutput<Schemas[K]>; }; /** Infer the input type of a Standard Schema, or a default type if the schema is undefined. */ type InferInputOrDefault<MaybeSchema, Default> = MaybeSchema extends StandardSchemaV1 ? StandardSchemaV1.InferInput<MaybeSchema> : Default; /** Infer the output type of a Standard Schema, or a default type if the schema is undefined. */ type InferOutputOrDefault<MaybeSchema, Default> = MaybeSchema extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<MaybeSchema> : Default; type Prettify<T> = { [K in keyof T]: T[K]; } & {}; type MaybePromise<T> = Promise<T> | T; type MaybeArray<T> = T | T[]; type NotObject = number | string | boolean | bigint | symbol | null | undefined | any[]; type VEList<K = undefined> = K extends any[] ? MaybeArray<{ _errors?: string[]; }> : { _errors?: string[]; }; type SchemaErrors<S> = { [K in keyof S]?: S[K] extends NotObject ? Prettify<VEList<S[K]>> : Prettify<VEList> & SchemaErrors<S[K]>; } & {}; type IssueWithUnionErrors = StandardSchemaV1.Issue & { unionErrors?: { issues: StandardSchemaV1.Issue[]; }[]; }; /** * Type of the returned object when validation fails. */ type ValidationErrors<S extends StandardSchemaV1 | undefined> = S extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<S> extends NotObject ? Prettify<VEList> : Prettify<VEList> & SchemaErrors<StandardSchemaV1.InferOutput<S>> : undefined; /** * 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 the function used to format validation errors. */ type HandleValidationErrorsShapeFn< S extends StandardSchemaV1 | undefined, BAS extends readonly StandardSchemaV1[], MD, Ctx extends object, CVE, > = ( validationErrors: ValidationErrors<S>, utils: { clientInput: InferInputOrDefault<S, undefined>; bindArgsClientInputs: InferInputArray<BAS>; metadata: MD; ctx: Prettify<Ctx>; } ) => Promise<CVE>; declare class SafeActionClient< ServerError, ODVES extends DVES | undefined, // override default validation errors shape MetadataSchema extends StandardSchemaV1 | undefined = undefined, MD = InferOutputOrDefault<MetadataSchema, undefined>, // metadata type (inferred from metadata schema) MDProvided extends boolean = MetadataSchema extends undefined ? true : false, Ctx extends object = {}, ISF extends (() => Promise<StandardSchemaV1>) | undefined = undefined, // input schema function IS extends StandardSchemaV1 | undefined = ISF extends Function ? Awaited<ReturnType<ISF>> : undefined, // input schema OS extends StandardSchemaV1 | undefined = undefined, // output schema const BAS extends readonly StandardSchemaV1[] = [], CVE = undefined, > { #private; constructor( args: SafeActionClientArgs<ServerError, ODVES, MetadataSchema, MD, MDProvided, Ctx, ISF, IS, OS, BAS, CVE> ); /** * 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, MDProvided, Ctx & NextCtx, ISF, IS, OS, BAS, CVE>; /** * 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, true, Ctx, ISF, IS, OS, BAS, CVE>; /** * 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} */ inputSchema< OIS extends StandardSchemaV1 | ((prevSchema: IS) => Promise<StandardSchemaV1>), // override input schema AIS extends StandardSchemaV1 = OIS extends (prevSchema: IS) => Promise<StandardSchemaV1> ? Awaited<ReturnType<OIS>> : OIS, OCVE = ODVES extends "flattened" ? FlattenedValidationErrors<ValidationErrors<AIS>> : ValidationErrors<AIS>, >( inputSchema: OIS, utils?: { handleValidationErrorsShape?: HandleValidationErrorsShapeFn<AIS, BAS, MD, Ctx, OCVE>; } ): SafeActionClient<ServerError, ODVES, MetadataSchema, MD, MDProvided, Ctx, ISF, AIS, OS, BAS, OCVE>; /** * @deprecated Alias for `inputSchema` method. Use that instead. */ schema: < OIS extends StandardSchemaV1 | ((prevSchema: IS) => Promise<StandardSchemaV1>), AIS extends StandardSchemaV1 = OIS extends (prevSchema: IS) => Promise<StandardSchemaV1> ? Awaited<ReturnType<OIS>> : OIS, OCVE = ODVES extends "flattened" ? { formErrors: string[]; fieldErrors: { [K in keyof Omit<ValidationErrors<AIS>, "_errors">]?: string[] | undefined }; } : ValidationErrors<AIS>, >( inputSchema: OIS, utils?: { handleValidationErrorsShape?: HandleValidationErrorsShapeFn<AIS, BAS, MD, Ctx, OCVE>; } ) => SafeActionClient<ServerError, ODVES, MetadataSchema, MD, MDProvided, Ctx, ISF, AIS, OS, BAS, OCVE>; /** * Define the bind args input validation schema for the action. * @param bindArgsSchemas Bind args input validation schemas * * {@link https://next-safe-action.dev/docs/define-actions/instance-methods#bindargsschemas See docs for more information} */ bindArgsSchemas<const OBAS extends readonly StandardSchemaV1[]>( bindArgsSchemas: OBAS ): SafeActionClient<ServerError, ODVES, MetadataSchema, MD, MDProvided, Ctx, ISF, IS, OS, OBAS, CVE>; /** * 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 StandardSchemaV1>( dataSchema: OOS ): SafeActionClient<ServerError, ODVES, MetadataSchema, MD, MDProvided, Ctx, ISF, IS, OOS, BAS, CVE>; /** * 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 InferOutputOrDefault<OS, any>>( this: MDProvided extends true ? SafeActionClient<ServerError, ODVES, MetadataSchema, MD, MDProvided, Ctx, ISF, IS, OS, BAS, CVE> : never, serverCodeFn: ServerCodeFn<MD, Ctx, IS, BAS, Data>, utils?: SafeActionUtils<ServerError, MD, Ctx, IS, BAS, CVE, Data> ): SafeActionFn<ServerError, IS, BAS, CVE, 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 InferOutputOrDefault<OS, any>>( this: MDProvided extends true ? SafeActionClient<ServerError, ODVES, MetadataSchema, MD, MDProvided, Ctx, ISF, IS, OS, BAS, CVE> : never, serverCodeFn: StateServerCodeFn<ServerError, MD, Ctx, IS, BAS, CVE, Data>, utils?: SafeActionUtils<ServerError, MD, Ctx, IS, BAS, CVE, Data> ): SafeStateActionFn<ServerError, IS, BAS, CVE, 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 StandardSchemaV1 | undefined> = { clientInput: unknown; bindArgsClientInputs: unknown[]; ctx: object; metadata: InferOutputOrDefault<MetadataSchema, undefined>; }; type HandleServerErrorFn<ServerError = string, MetadataSchema extends StandardSchemaV1 | undefined = undefined> = ( error: Error, utils: ServerErrorFunctionUtils<MetadataSchema> ) => MaybePromise<ServerError>; /** * Type of the arguments passed to the `SafeActionClient` constructor. */ type SafeActionClientArgs< ServerError, ODVES extends DVES | undefined, // override default validation errors shape MetadataSchema extends StandardSchemaV1 | undefined = undefined, MD = InferOutputOrDefault<MetadataSchema, undefined>, // metadata type (inferred from metadata schema) MDProvided extends boolean = MetadataSchema extends undefined ? true : false, Ctx extends object = {}, ISF extends (() => Promise<StandardSchemaV1>) | undefined = undefined, // input schema function IS extends StandardSchemaV1 | undefined = ISF extends Function ? Awaited<ReturnType<ISF>> : undefined, // input schema OS extends StandardSchemaV1 | undefined = undefined, // output schema BAS extends readonly StandardSchemaV1[] = [], // bind args schemas CVE = undefined, > = { middlewareFns: MiddlewareFn<ServerError, any, any, any>[]; metadataSchema: MetadataSchema; metadata: MD; metadataProvided?: MDProvided; inputSchemaFn: ISF; outputSchema: OS; bindArgsSchemas: BAS; handleValidationErrorsShape: HandleValidationErrorsShapeFn<IS, BAS, MD, Ctx, CVE>; ctxType: Ctx; handleServerError: HandleServerErrorFn<ServerError, MetadataSchema>; defaultValidationErrorsShape: ODVES; throwValidationErrors: boolean; }; /** * Type of options when creating a new safe action client. */ type CreateClientOpts< ODVES extends DVES | undefined = undefined, ServerError = string, MetadataSchema extends StandardSchemaV1 | undefined = undefined, > = { defineMetadataSchema?: () => MetadataSchema; handleServerError?: HandleServerErrorFn<ServerError, MetadataSchema>; defaultValidationErrorsShape?: ODVES; throwValidationErrors?: boolean; }; /** * Type of the result of a safe action. */ type SafeActionResult< ServerError, S extends StandardSchemaV1 | undefined, CVE = ValidationErrors<S>, Data = unknown, NextCtx = object, > = { data?: Data; serverError?: ServerError; validationErrors?: CVE; }; /** * Type of the function called from components with type safe input data. */ type SafeActionFn< ServerError, S extends StandardSchemaV1 | undefined, BAS extends readonly StandardSchemaV1[], CVE, Data, > = ( ...clientInputs: [...bindArgsInputs: InferInputArray<BAS>, input: InferInputOrDefault<S, void>] ) => Promise<SafeActionResult<ServerError, S, CVE, Data>>; /** * Type of the stateful function called from components with type safe input data. */ type SafeStateActionFn< ServerError, S extends StandardSchemaV1 | undefined, BAS extends readonly StandardSchemaV1[], CVE, Data, > = ( ...clientInputs: [ ...bindArgsInputs: InferInputArray<BAS>, prevResult: Prettify<SafeActionResult<ServerError, S, CVE, Data>>, input: InferInputOrDefault<S, void>, ] ) => Promise<SafeActionResult<ServerError, S, CVE, 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, NextCtx> & { navigationKind?: NavigationKind; 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 StandardSchemaV1 | undefined, BAS extends readonly StandardSchemaV1[], Data, > = (args: { parsedInput: InferOutputOrDefault<S, undefined>; clientInput: InferInputOrDefault<S, undefined>; bindArgsParsedInputs: InferOutputArray<BAS>; bindArgsClientInputs: InferInputArray<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 StandardSchemaV1 | undefined, BAS extends readonly StandardSchemaV1[], CVE, Data, > = ( args: { parsedInput: InferOutputOrDefault<S, undefined>; clientInput: InferInputOrDefault<S, undefined>; bindArgsParsedInputs: InferOutputArray<BAS>; bindArgsClientInputs: InferInputArray<BAS>; ctx: Prettify<Ctx>; metadata: MD; }, utils: { prevResult: Prettify<SafeActionResult<ServerError, S, CVE, Data>>; } ) => Promise<Data>; /** * Possible types of navigation. */ type NavigationKind = "redirect" | "notFound" | "forbidden" | "unauthorized" | "other"; /** * Type of action execution utils. It includes action callbacks and other utils. */ type SafeActionUtils< ServerError, MD, Ctx extends object, S extends StandardSchemaV1 | undefined, BAS extends readonly StandardSchemaV1[], CVE, Data, > = { throwServerError?: boolean; throwValidationErrors?: | boolean | { overrideErrorMessage: (validationErrors: CVE) => Promise<string>; }; onSuccess?: (args: { data?: Data; metadata: MD; ctx?: Prettify<Ctx>; clientInput: InferInputOrDefault<S, undefined>; bindArgsClientInputs: InferInputArray<BAS>; parsedInput: InferOutputOrDefault<S, undefined>; bindArgsParsedInputs: InferOutputArray<BAS>; }) => Promise<unknown>; onNavigation?: (args: { metadata: MD; ctx?: Prettify<Ctx>; clientInput: InferInputOrDefault<S, undefined>; bindArgsClientInputs: InferInputArray<BAS>; navigationKind: NavigationKind; }) => Promise<unknown>; onError?: (args: { error: Prettify<Omit<SafeActionResult<ServerError, S, CVE, Data>, "data">>; metadata: MD; ctx?: Prettify<Ctx>; clientInput: InferInputOrDefault<S, undefined>; bindArgsClientInputs: InferInputArray<BAS>; }) => Promise<unknown>; onSettled?: (args: { result: Prettify<SafeActionResult<ServerError, S, CVE, Data>>; metadata: MD; ctx?: Prettify<Ctx>; clientInput: InferInputOrDefault<S, undefined>; bindArgsClientInputs: InferInputArray<BAS>; navigationKind?: NavigationKind; }) => Promise<unknown>; }; /** * Infer input types of a safe action. */ type InferSafeActionFnInput<T extends Function> = T extends | SafeActionFn< any, infer S extends StandardSchemaV1 | undefined, infer BAS extends readonly StandardSchemaV1[], any, any > | SafeStateActionFn< any, infer S extends StandardSchemaV1 | undefined, infer BAS extends readonly StandardSchemaV1[], any, any > ? S extends StandardSchemaV1 ? { clientInput: StandardSchemaV1.InferInput<S>; bindArgsClientInputs: InferInputArray<BAS>; parsedInput: StandardSchemaV1.InferOutput<S>; bindArgsParsedInputs: InferOutputArray<BAS>; } : { clientInput: undefined; bindArgsClientInputs: InferInputArray<BAS>; parsedInput: undefined; bindArgsParsedInputs: InferOutputArray<BAS>; } : never; /** * Infer the result type of a safe action. */ type InferSafeActionFnResult<T extends Function> = T extends | SafeActionFn<infer ServerError, infer S extends StandardSchemaV1 | undefined, any, infer CVE, infer Data> | SafeStateActionFn<infer ServerError, infer S extends StandardSchemaV1 | undefined, any, infer CVE, infer Data> ? SafeActionResult<ServerError, S, CVE, 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, false, 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, false, 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, any> | MiddlewareFn<infer ServerError, any, any, any> | SafeActionFn<infer ServerError, any, any, any, any> | SafeStateActionFn<infer ServerError, any, any, any, any> ? ServerError : never; export { type CreateClientOpts as C, type DVES as D, type FlattenedValidationErrors as F, type HandleServerErrorFn as H, type InferInputOrDefault as I, type MiddlewareFn as M, type NavigationKind as N, type Prettify as P, StandardSchemaV1 as S, type ValidationErrors as V, SafeActionClient as a, type InferOutputOrDefault as b, type ServerErrorFunctionUtils as c, type SafeActionClientArgs as d, type SafeActionResult as e, type SafeActionFn as f, type SafeStateActionFn as g, type MiddlewareResult as h, type ServerCodeFn as i, type StateServerCodeFn as j, type SafeActionUtils as k, type InferSafeActionFnInput as l, type InferSafeActionFnResult as m, type InferMiddlewareFnNextCtx as n, type InferCtx as o, type InferMetadata as p, type InferServerError as q, type IssueWithUnionErrors as r, type HandleValidationErrorsShapeFn as s, type MaybePromise as t, };