Skip to content

Commit

Permalink
refactor: improve internal code (#150)
Browse files Browse the repository at this point in the history
Commits in this PR improve internal safe action client class code.
  • Loading branch information
TheEdoRan committed Jun 4, 2024
1 parent 54b0b52 commit 8e19d94
Show file tree
Hide file tree
Showing 14 changed files with 424 additions and 398 deletions.
288 changes: 140 additions & 148 deletions packages/next-safe-action/src/action-builder.ts

Large diffs are not rendered by default.

48 changes: 24 additions & 24 deletions packages/next-safe-action/src/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ const getActionStatus = <
ServerError,
S extends Schema | undefined,
const BAS extends readonly Schema[],
FVE,
FBAVE,
CVE,
CBAVE,
Data,
>({
isIdle,
Expand All @@ -39,7 +39,7 @@ const getActionStatus = <
}: {
isIdle: boolean;
isExecuting: boolean;
result: HookResult<ServerError, S, BAS, FVE, FBAVE, Data>;
result: HookResult<ServerError, S, BAS, CVE, CBAVE, Data>;
}): HookActionStatus => {
if (isIdle) {
return "idle";
Expand Down Expand Up @@ -70,19 +70,19 @@ const useActionCallbacks = <
ServerError,
S extends Schema | undefined,
const BAS extends readonly Schema[],
FVE,
FBAVE,
CVE,
CBAVE,
Data,
>({
result,
input,
status,
cb,
}: {
result: HookResult<ServerError, S, BAS, FVE, FBAVE, Data>;
result: HookResult<ServerError, S, BAS, CVE, CBAVE, Data>;
input: S extends Schema ? InferIn<S> : undefined;
status: HookActionStatus;
cb?: HookCallbacks<ServerError, S, BAS, FVE, FBAVE, Data>;
cb?: HookCallbacks<ServerError, S, BAS, CVE, CBAVE, Data>;
}) => {
const onExecuteRef = React.useRef(cb?.onExecute);
const onSuccessRef = React.useRef(cb?.onSuccess);
Expand Down Expand Up @@ -129,20 +129,20 @@ export const useAction = <
ServerError,
S extends Schema | undefined,
const BAS extends readonly Schema[],
FVE,
FBAVE,
CVE,
CBAVE,
Data,
>(
safeActionFn: HookSafeActionFn<ServerError, S, BAS, FVE, FBAVE, Data>,
utils?: HookCallbacks<ServerError, S, BAS, FVE, FBAVE, Data>
safeActionFn: HookSafeActionFn<ServerError, S, BAS, CVE, CBAVE, Data>,
utils?: HookCallbacks<ServerError, S, BAS, CVE, CBAVE, Data>
) => {
const [, startTransition] = React.useTransition();
const [result, setResult] = React.useState<HookResult<ServerError, S, BAS, FVE, FBAVE, Data>>(EMPTY_HOOK_RESULT);
const [result, setResult] = React.useState<HookResult<ServerError, S, BAS, CVE, CBAVE, Data>>(EMPTY_HOOK_RESULT);
const [clientInput, setClientInput] = React.useState<S extends Schema ? InferIn<S> : void>();
const [isExecuting, setIsExecuting] = React.useState(false);
const [isIdle, setIsIdle] = React.useState(true);

const status = getActionStatus<ServerError, S, BAS, FVE, FBAVE, Data>({ isExecuting, result, isIdle });
const status = getActionStatus<ServerError, S, BAS, CVE, CBAVE, Data>({ isExecuting, result, isIdle });

const execute = React.useCallback(
(input: S extends Schema ? InferIn<S> : void) => {
Expand Down Expand Up @@ -233,19 +233,19 @@ export const useOptimisticAction = <
ServerError,
S extends Schema | undefined,
const BAS extends readonly Schema[],
FVE,
FBAVE,
CVE,
CBAVE,
Data,
State,
>(
safeActionFn: HookSafeActionFn<ServerError, S, BAS, FVE, FBAVE, Data>,
safeActionFn: HookSafeActionFn<ServerError, S, BAS, CVE, CBAVE, Data>,
utils: {
currentState: State;
updateFn: (state: State, input: S extends Schema ? InferIn<S> : undefined) => State;
} & HookCallbacks<ServerError, S, BAS, FVE, FBAVE, Data>
} & HookCallbacks<ServerError, S, BAS, CVE, CBAVE, Data>
) => {
const [, startTransition] = React.useTransition();
const [result, setResult] = React.useState<HookResult<ServerError, S, BAS, FVE, FBAVE, Data>>(EMPTY_HOOK_RESULT);
const [result, setResult] = React.useState<HookResult<ServerError, S, BAS, CVE, CBAVE, Data>>(EMPTY_HOOK_RESULT);
const [clientInput, setClientInput] = React.useState<S extends Schema ? InferIn<S> : void>();
const [isExecuting, setIsExecuting] = React.useState(false);
const [isIdle, setIsIdle] = React.useState(true);
Expand All @@ -254,7 +254,7 @@ export const useOptimisticAction = <
utils.updateFn
);

const status = getActionStatus<ServerError, S, BAS, FVE, FBAVE, Data>({ isExecuting, result, isIdle });
const status = getActionStatus<ServerError, S, BAS, CVE, CBAVE, Data>({ isExecuting, result, isIdle });

const execute = React.useCallback(
(input: S extends Schema ? InferIn<S> : void) => {
Expand Down Expand Up @@ -353,15 +353,15 @@ export const useStateAction = <
ServerError,
S extends Schema | undefined,
const BAS extends readonly Schema[],
FVE,
FBAVE,
CVE,
CBAVE,
Data,
>(
safeActionFn: HookSafeStateActionFn<ServerError, S, BAS, FVE, FBAVE, Data>,
safeActionFn: HookSafeStateActionFn<ServerError, S, BAS, CVE, CBAVE, Data>,
utils?: {
initResult?: Awaited<ReturnType<typeof safeActionFn>>;
permalink?: string;
} & HookCallbacks<ServerError, S, BAS, FVE, FBAVE, Data>
} & HookCallbacks<ServerError, S, BAS, CVE, CBAVE, Data>
) => {
const [result, dispatcher, isExecuting] = React.useActionState(
safeActionFn,
Expand All @@ -370,7 +370,7 @@ export const useStateAction = <
);
const [isIdle, setIsIdle] = React.useState(true);
const [clientInput, setClientInput] = React.useState<S extends Schema ? InferIn<S> : void>();
const status = getActionStatus<ServerError, S, BAS, FVE, FBAVE, Data>({ isExecuting, result, isIdle });
const status = getActionStatus<ServerError, S, BAS, CVE, CBAVE, Data>({ isExecuting, result, isIdle });

const execute = React.useCallback(
(input: S extends Schema ? InferIn<S> : void) => {
Expand Down
28 changes: 14 additions & 14 deletions packages/next-safe-action/src/hooks.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ export type HookResult<
ServerError,
S extends Schema | undefined,
BAS extends readonly Schema[],
FVE,
FBAVE,
CVE,
CBAVE,
Data,
> = SafeActionResult<ServerError, S, BAS, FVE, FBAVE, Data> & {
> = SafeActionResult<ServerError, S, BAS, CVE, CBAVE, Data> & {
fetchError?: string;
};

Expand All @@ -24,18 +24,18 @@ export type HookCallbacks<
ServerError,
S extends Schema | undefined,
BAS extends readonly Schema[],
FVE,
FBAVE,
CVE,
CBAVE,
Data,
> = {
onExecute?: (args: { input: S extends Schema ? InferIn<S> : undefined }) => MaybePromise<void>;
onSuccess?: (args: { data: Data; input: S extends Schema ? InferIn<S> : undefined }) => MaybePromise<void>;
onError?: (args: {
error: Omit<HookResult<ServerError, S, BAS, FVE, FBAVE, Data>, "data">;
error: Omit<HookResult<ServerError, S, BAS, CVE, CBAVE, Data>, "data">;
input: S extends Schema ? InferIn<S> : undefined;
}) => MaybePromise<void>;
onSettled?: (args: {
result: HookResult<ServerError, S, BAS, FVE, FBAVE, Data>;
result: HookResult<ServerError, S, BAS, CVE, CBAVE, Data>;
input: S extends Schema ? InferIn<S> : undefined;
}) => MaybePromise<void>;
};
Expand All @@ -48,12 +48,12 @@ export type HookSafeActionFn<
ServerError,
S extends Schema | undefined,
BAS extends readonly Schema[],
FVE,
FBAVE,
CVE,
CBAVE,
Data,
> = (
input: S extends Schema ? InferIn<S> : undefined
) => Promise<SafeActionResult<ServerError, S, BAS, FVE, FBAVE, Data>>;
) => Promise<SafeActionResult<ServerError, S, BAS, CVE, CBAVE, Data>>;

/**
* Type of the stateful safe action function passed to hooks. Same as `SafeStateActionFn` except it accepts
Expand All @@ -63,13 +63,13 @@ export type HookSafeStateActionFn<
ServerError,
S extends Schema | undefined,
BAS extends readonly Schema[],
FVE,
FBAVE,
CVE,
CBAVE,
Data,
> = (
prevResult: SafeActionResult<ServerError, S, BAS, FVE, FBAVE, Data>,
prevResult: SafeActionResult<ServerError, S, BAS, CVE, CBAVE, Data>,
input: S extends Schema ? InferIn<S> : undefined
) => Promise<SafeActionResult<ServerError, S, BAS, FVE, FBAVE, Data>>;
) => Promise<SafeActionResult<ServerError, S, BAS, CVE, CBAVE, Data>>;

/**
* Type of the action status returned by `useAction` and `useOptimisticAction` hooks.
Expand Down
16 changes: 10 additions & 6 deletions packages/next-safe-action/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import type { Infer, Schema } from "@typeschema/main";
import type { SafeActionClientOpts } from "./index.types";
import { SafeActionClient } from "./safe-action-client";
import { DEFAULT_SERVER_ERROR_MESSAGE } from "./utils";
import { formatBindArgsValidationErrors, formatValidationErrors } from "./validation-errors";

export { DEFAULT_SERVER_ERROR_MESSAGE } from "./utils";
export { ActionMetadataError, DEFAULT_SERVER_ERROR_MESSAGE } from "./utils";
export { flattenBindArgsValidationErrors, flattenValidationErrors, returnValidationErrors } from "./validation-errors";

export type * from "./index.types";
Expand Down Expand Up @@ -36,14 +37,17 @@ export const createSafeActionClient = <ServerError = string, MetadataSchema exte
SafeActionClientOpts<ServerError, MetadataSchema>["handleReturnedServerError"]
>;

return new SafeActionClient<
ServerError,
undefined,
MetadataSchema extends Schema ? Infer<MetadataSchema> : undefined
>({
return new SafeActionClient({
middlewareFns: [async ({ next }) => next({ ctx: undefined })],
handleServerErrorLog,
handleReturnedServerError,
validationStrategy: "zod",
schema: undefined,
bindArgsSchemas: [],
ctxType: undefined,
metadataSchema: createOpts?.defineMetadataSchema?.(),
metadata: undefined as MetadataSchema extends Schema ? Infer<MetadataSchema> : undefined,
formatValidationErrorsFn: formatValidationErrors,
formatBindArgsValidationErrorsFn: formatBindArgsValidationErrors,
});
};
46 changes: 19 additions & 27 deletions packages/next-safe-action/src/index.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,24 @@ export type SafeActionResult<
ServerError,
S extends Schema | undefined,
BAS extends readonly Schema[],
FVE = ValidationErrors<S>,
FBAVE = BindArgsValidationErrors<BAS>,
CVE = ValidationErrors<S>,
CBAVE = BindArgsValidationErrors<BAS>,
Data = unknown,
// eslint-disable-next-line
NextCtx = unknown,
> = {
data?: Data;
serverError?: ServerError;
validationErrors?: FVE;
bindArgsValidationErrors?: FBAVE;
validationErrors?: CVE;
bindArgsValidationErrors?: CBAVE;
};

/**
* Type of the function called from components with type safe input data.
*/
export type SafeActionFn<ServerError, S extends Schema | undefined, BAS extends readonly Schema[], FVE, FBAVE, Data> = (
export 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, FVE, FBAVE, Data>>;
) => Promise<SafeActionResult<ServerError, S, BAS, CVE, CBAVE, Data>>;

/**
* Type of the stateful function called from components with type safe input data.
Expand All @@ -44,30 +44,22 @@ export type SafeStateActionFn<
ServerError,
S extends Schema | undefined,
BAS extends readonly Schema[],
FVE,
FBAVE,
CVE,
CBAVE,
Data,
> = (
...clientInputs: [
...bindArgsInputs: InferInArray<BAS>,
prevResult: Prettify<SafeActionResult<ServerError, S, BAS, FVE, FBAVE, Data>>,
prevResult: Prettify<SafeActionResult<ServerError, S, BAS, CVE, CBAVE, Data>>,
input: S extends Schema ? InferIn<S> : void,
]
) => Promise<SafeActionResult<ServerError, S, BAS, FVE, FBAVE, Data>>;
) => 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.
*/
export type MiddlewareResult<ServerError, NextCtx> = SafeActionResult<
ServerError,
any,
any,
unknown,
unknown,
unknown,
NextCtx
> & {
export type MiddlewareResult<ServerError, NextCtx> = SafeActionResult<ServerError, any, any, any, any, any, NextCtx> & {
parsedInput?: unknown;
bindArgsParsedInputs?: unknown[];
ctx?: unknown;
Expand All @@ -77,12 +69,12 @@ export type MiddlewareResult<ServerError, NextCtx> = SafeActionResult<
/**
* Type of the middleware function passed to a safe action client.
*/
export type MiddlewareFn<ServerError, Ctx, NextCtx, MD> = {
export type MiddlewareFn<ServerError, MD, Ctx, NextCtx> = {
(opts: {
clientInput: unknown;
bindArgsClientInputs: unknown[];
ctx: Ctx;
metadata: MD | undefined;
metadata: MD;
next: {
<NC>(opts: { ctx: NC }): Promise<MiddlewareResult<ServerError, NC>>;
};
Expand All @@ -92,7 +84,7 @@ export type MiddlewareFn<ServerError, Ctx, NextCtx, MD> = {
/**
* Type of the function that executes server code when defining a new safe action.
*/
export type ServerCodeFn<S extends Schema | undefined, BAS extends readonly Schema[], Ctx, MD, Data> = (args: {
export type ServerCodeFn<MD, Ctx, S extends Schema | undefined, BAS extends readonly Schema[], Data> = (args: {
parsedInput: S extends Schema ? Infer<S> : undefined;
bindArgsParsedInputs: InferArray<BAS>;
ctx: Ctx;
Expand All @@ -104,12 +96,12 @@ export type ServerCodeFn<S extends Schema | undefined, BAS extends readonly Sche
*/
export type StateServerCodeFn<
ServerError,
MD,
Ctx,
S extends Schema | undefined,
BAS extends readonly Schema[],
FVE,
FBAVE,
Ctx,
MD,
CVE,
CBAVE,
Data,
> = (
args: {
Expand All @@ -118,5 +110,5 @@ export type StateServerCodeFn<
ctx: Ctx;
metadata: MD;
},
utils: { prevResult: Prettify<SafeActionResult<ServerError, S, BAS, FVE, FBAVE, Data>> }
utils: { prevResult: Prettify<SafeActionResult<ServerError, S, BAS, CVE, CBAVE, Data>> }
) => Promise<Data>;
Loading

0 comments on commit 8e19d94

Please sign in to comment.