Skip to content

Commit

Permalink
refactor: set up built-in multi validation system
Browse files Browse the repository at this point in the history
  • Loading branch information
TheEdoRan committed Jul 16, 2024
1 parent a148550 commit 10143bb
Show file tree
Hide file tree
Showing 16 changed files with 69 additions and 32 deletions.
5 changes: 5 additions & 0 deletions packages/next-safe-action/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@
"react-dom": ">= 18.2.0",
"zod": ">= 3.0.0"
},
"peerDependenciesMeta": {
"zod": {
"optional": true
}
},
"repository": {
"type": "git",
"url": "https://github.com/TheEdoRan/next-safe-action.git"
Expand Down
2 changes: 1 addition & 1 deletion packages/next-safe-action/src/action-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import type {
StateServerCodeFn,
} from "./index.types";
import { ActionMetadataError, DEFAULT_SERVER_ERROR_MESSAGE, isError, zodValidate } from "./utils";
import type { Infer, InferArray, InferIn, InferInArray, Schema } from "./utils.types";
import type { Infer, InferArray, InferIn, InferInArray, Schema } from "./validation-adapters";
import { ActionValidationError, buildValidationErrors } from "./validation-errors";
import type {
BindArgsValidationErrors,
Expand Down
2 changes: 1 addition & 1 deletion packages/next-safe-action/src/hooks-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from "react";
import {} from "react/experimental";
import type {} from "zod";
import type { HookActionStatus, HookCallbacks, HookResult } from "./hooks.types";
import type { InferIn, Schema } from "./utils.types";
import type { InferIn, Schema } from "./validation-adapters";

export const getActionStatus = <
ServerError,
Expand Down
2 changes: 1 addition & 1 deletion packages/next-safe-action/src/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type {} from "zod";
import { getActionShorthandStatusObject, getActionStatus, useActionCallbacks } from "./hooks-utils";
import type { HookCallbacks, HookResult, HookSafeActionFn } from "./hooks.types";
import { isError } from "./utils";
import type { InferIn, Schema } from "./utils.types";
import type { InferIn, Schema } from "./validation-adapters";

// HOOKS

Expand Down
3 changes: 2 additions & 1 deletion packages/next-safe-action/src/hooks.types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { SafeActionResult } from "./index.types";
import type { InferIn, MaybePromise, Prettify, Schema } from "./utils.types";
import type { MaybePromise, Prettify } from "./utils.types";
import type { InferIn, Schema } from "./validation-adapters";

/**
* Type of `result` object returned by `useAction`, `useOptimisticAction` and `useStateAction` hooks.
Expand Down
2 changes: 1 addition & 1 deletion packages/next-safe-action/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { DVES, SafeActionClientOpts } from "./index.types";
import { SafeActionClient } from "./safe-action-client";
import { DEFAULT_SERVER_ERROR_MESSAGE } from "./utils";
import type { Infer, Schema } from "./utils.types";
import type { Infer, Schema } from "./validation-adapters";
import {
flattenBindArgsValidationErrors,
flattenValidationErrors,
Expand Down
3 changes: 2 additions & 1 deletion packages/next-safe-action/src/index.types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Infer, InferArray, InferIn, InferInArray, MaybePromise, Prettify, Schema } from "./utils.types";
import type { MaybePromise, Prettify } from "./utils.types";
import type { Infer, InferArray, InferIn, InferInArray, Schema } from "./validation-adapters";
import type { BindArgsValidationErrors, ValidationErrors } from "./validation-errors.types";

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/next-safe-action/src/safe-action-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type {
ServerCodeFn,
StateServerCodeFn,
} from "./index.types";
import type { Infer, Schema } from "./utils.types";
import type { Infer, Schema } from "./validation-adapters";
import type {
BindArgsValidationErrors,
FlattenedBindArgsValidationErrors,
Expand Down
2 changes: 1 addition & 1 deletion packages/next-safe-action/src/stateful-hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {} from "react/experimental";
import type {} from "zod";
import { getActionShorthandStatusObject, getActionStatus, useActionCallbacks } from "./hooks-utils";
import type { HookCallbacks, HookSafeStateActionFn } from "./hooks.types";
import type { InferIn, Schema } from "./utils.types";
import type { InferIn, Schema } from "./validation-adapters";
/**
* Use the stateful action from a Client Component via hook. Used for actions defined with [`stateAction`](https://next-safe-action.dev/docs/safe-action-client/instance-methods#action--stateaction).
* @param safeActionFn The action function
Expand Down
2 changes: 1 addition & 1 deletion packages/next-safe-action/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Infer, Schema } from "./utils.types";
import type { Infer, Schema } from "./validation-adapters";

export const DEFAULT_SERVER_ERROR_MESSAGE = "Something went wrong while executing the operation.";

Expand Down
21 changes: 0 additions & 21 deletions packages/next-safe-action/src/utils.types.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,7 @@
import type { z } from "zod";

// Takes an object type and makes it more readable.
export type Prettify<T> = {
[K in keyof T]: T[K];
} & {};

// Returns type or promise of type.
export type MaybePromise<T> = Promise<T> | T;

// Schema type.
export type Schema = z.ZodType;

// Infers output schema type.
export type Infer<S extends Schema> = z.infer<S>;

// Infers input schema type.
export type InferIn<S extends Schema> = z.input<S>;

// Infers output schema type in array of schemas.
export type InferArray<BAS extends readonly Schema[]> = {
[K in keyof BAS]: Infer<BAS[K]>;
};

// Infers input schema type in array of schemas.
export type InferInArray<BAS extends readonly Schema[]> = {
[K in keyof BAS]: InferIn<BAS[K]>;
};
3 changes: 3 additions & 0 deletions packages/next-safe-action/src/validation-adapters/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { zodAdapter } from "./libs/zod";

export * from "./types";
24 changes: 24 additions & 0 deletions packages/next-safe-action/src/validation-adapters/libs/zod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { z } from "zod";
import type { Infer, ValidationAdapter } from "../types";

class ZodAdapter<S extends z.ZodType> implements ValidationAdapter<S> {
async validate(schema: S, data: unknown) {
const result = await schema.safeParseAsync(data);

if (result.success) {
return {
success: true,
data: result.data as Infer<S>,
} as const;
}

return {
success: false,
issues: result.error.issues.map(({ message, path }) => ({ message, path })),
} as const;
}
}

export function zodAdapter() {
return new ZodAdapter<z.ZodType>();
}
23 changes: 23 additions & 0 deletions packages/next-safe-action/src/validation-adapters/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { z } from "zod";

export type Schema = z.ZodType;
export type Infer<S extends Schema> = S extends z.ZodType ? z.infer<S> : never;
export type InferIn<S extends Schema> = S extends z.ZodType ? z.input<S> : never;
export type InferArray<BAS extends readonly Schema[]> = {
[K in keyof BAS]: Infer<BAS[K]>;
};
export type InferInArray<BAS extends readonly Schema[]> = {
[K in keyof BAS]: InferIn<BAS[K]>;
};

export type ValidationIssue = {
message: string;
path?: Array<string | number | symbol>;
};

export interface ValidationAdapter<S extends Schema> {
validate(
schema: S,
data: unknown
): Promise<{ success: true; data: Infer<S> } | { success: false; issues: ValidationIssue[] }>;
}
2 changes: 1 addition & 1 deletion packages/next-safe-action/src/validation-errors.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment */

import type { Schema } from "./utils.types";
import type { Schema } from "./validation-adapters";
import type {
FlattenedBindArgsValidationErrors,
FlattenedValidationErrors,
Expand Down
3 changes: 2 additions & 1 deletion packages/next-safe-action/src/validation-errors.types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Infer, Prettify, Schema } from "./utils.types";
import type { Prettify } from "./utils.types";
import type { Infer, Schema } from "./validation-adapters";

export type ValidationIssue = {
message: string;
Expand Down

0 comments on commit 10143bb

Please sign in to comment.