Skip to content

Commit 674c24d

Browse files
committed
Changed withValidation to withZodValidation
1 parent 74f6479 commit 674c24d

File tree

5 files changed

+142
-65
lines changed

5 files changed

+142
-65
lines changed

docs/content/server/with-zod-validation.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ This middleware validates input against a Zod-compatible schema:
1010

1111
```ts
1212
import { z } from "zod";
13-
import { withValidation, applyMiddleware, serverAction } from "use-server-action/server";
13+
import { withZodValidation, applyMiddleware, serverAction } from "use-server-action/server";
1414

1515
const CreateUserSchema = z.object({
1616
name: z.string().min(1, "Name is required"),
@@ -29,7 +29,7 @@ export const validatedCreateUser = applyMiddleware(createUser, [
2929
#### Options
3030

3131
```ts
32-
withValidation(schema, {
32+
withZodValidation(schema, {
3333
// Custom error code (default: "VALIDATION_ERROR")
3434
code: "INVALID_INPUT",
3535

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "use-server-action",
3-
"version": "1.1.4",
3+
"version": "1.1.5",
44
"description": "A React hook for working with Next.js server actions",
55
"main": "./dist/index.js",
66
"module": "./dist/index.mjs",

src/server/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ export {
1818
createMiddleware,
1919
applyMiddleware,
2020
composeMiddleware,
21-
withValidation,
21+
withZodValidation,
2222
withLogging,
2323
} from "./middleware";
2424
export type {
2525
Middleware,
26-
ValidationSchema,
27-
WithValidationOptions,
26+
ValidationZodSchema,
27+
WithZodValidationOptions,
2828
} from "./middleware";

src/server/middleware.test.ts

Lines changed: 122 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import {
55
composeMiddleware,
66
createMiddleware,
77
withLogging,
8-
withValidation,
9-
type ValidationSchema,
8+
withZodValidation,
9+
type ValidationZodSchema,
1010
} from "./middleware";
1111

1212
type TestData = { value: string };
@@ -47,7 +47,9 @@ describe("middleware", () => {
4747
);
4848

4949
const action = vi.fn(
50-
async (input: string): Promise<ServerActionResult<TestData>> => {
50+
async (
51+
input: string,
52+
): Promise<ServerActionResult<TestData>> => {
5153
return { ok: true, data: { value: input } };
5254
},
5355
);
@@ -61,7 +63,11 @@ describe("middleware", () => {
6163
const middleware = createMiddleware<[string], TestData>(
6264
async (next, input) => {
6365
if (input === "blocked") {
64-
return { ok: false, message: "Blocked", code: "BLOCKED" };
66+
return {
67+
ok: false,
68+
message: "Blocked",
69+
code: "BLOCKED",
70+
};
6571
}
6672
return next(input);
6773
},
@@ -70,7 +76,11 @@ describe("middleware", () => {
7076
const action = createSuccessAction({ value: "test" });
7177
const result = await middleware(action, "blocked");
7278

73-
expect(result).toEqual({ ok: false, message: "Blocked", code: "BLOCKED" });
79+
expect(result).toEqual({
80+
ok: false,
81+
message: "Blocked",
82+
code: "BLOCKED",
83+
});
7484
expect(action).not.toHaveBeenCalled();
7585
});
7686

@@ -89,7 +99,10 @@ describe("middleware", () => {
8999
const action = createSuccessAction({ value: "original" });
90100
const result = await middleware(action);
91101

92-
expect(result).toEqual({ ok: true, data: { value: "original_modified" } });
102+
expect(result).toEqual({
103+
ok: true,
104+
data: { value: "original_modified" },
105+
});
93106
});
94107
});
95108

@@ -104,10 +117,12 @@ describe("middleware", () => {
104117
return result;
105118
});
106119

107-
const action = vi.fn(async (): Promise<ServerActionResult<TestData>> => {
108-
callOrder.push("action");
109-
return { ok: true, data: { value: "test" } };
110-
});
120+
const action = vi.fn(
121+
async (): Promise<ServerActionResult<TestData>> => {
122+
callOrder.push("action");
123+
return { ok: true, data: { value: "test" } };
124+
},
125+
);
111126

112127
const wrapped = applyMiddleware(action, [middleware]);
113128
await wrapped();
@@ -136,10 +151,12 @@ describe("middleware", () => {
136151
return result;
137152
});
138153

139-
const action = vi.fn(async (): Promise<ServerActionResult<TestData>> => {
140-
callOrder.push("action");
141-
return { ok: true, data: { value: "test" } };
142-
});
154+
const action = vi.fn(
155+
async (): Promise<ServerActionResult<TestData>> => {
156+
callOrder.push("action");
157+
return { ok: true, data: { value: "test" } };
158+
},
159+
);
143160

144161
const wrapped = applyMiddleware(action, [first, second]);
145162
await wrapped();
@@ -172,7 +189,10 @@ describe("middleware", () => {
172189
const wrapped = applyMiddleware(action, [middleware]);
173190
const result = await wrapped("test", 5);
174191

175-
expect(result).toEqual({ ok: true, data: { value: "test_modified:6" } });
192+
expect(result).toEqual({
193+
ok: true,
194+
data: { value: "test_modified:6" },
195+
});
176196
});
177197
});
178198

@@ -202,7 +222,9 @@ describe("middleware", () => {
202222
describe("withLogging", () => {
203223
it("should call onCall with params", async () => {
204224
const onCall = vi.fn();
205-
const middleware = withLogging<[string, number], TestData>({ onCall });
225+
const middleware = withLogging<[string, number], TestData>({
226+
onCall,
227+
});
206228
const action = createSuccessAction({ value: "test" });
207229

208230
await middleware(action, "hello", 42);
@@ -217,7 +239,9 @@ describe("middleware", () => {
217239

218240
await middleware(action, "input");
219241

220-
expect(onSuccess).toHaveBeenCalledWith({ value: "test" }, ["input"]);
242+
expect(onSuccess).toHaveBeenCalledWith({ value: "test" }, [
243+
"input",
244+
]);
221245
});
222246

223247
it("should call onError for error results", async () => {
@@ -248,16 +272,22 @@ describe("middleware", () => {
248272

249273
// Mock schema that mimics Zod's safeParse interface
250274
const createMockSchema = <T>(
251-
validator: (data: unknown) => { valid: boolean; data?: T; message?: string },
252-
): ValidationSchema<T> => ({
275+
validator: (data: unknown) => {
276+
valid: boolean;
277+
data?: T;
278+
message?: string;
279+
},
280+
): ValidationZodSchema<T> => ({
253281
safeParse: (data: unknown) => {
254282
const result = validator(data);
255283
if (result.valid) {
256284
return { success: true, data: result.data as T };
257285
}
258286
return {
259287
success: false,
260-
error: { errors: [{ message: result.message ?? "Invalid" }] },
288+
error: {
289+
errors: [{ message: result.message ?? "Invalid" }],
290+
},
261291
};
262292
},
263293
});
@@ -275,27 +305,44 @@ describe("middleware", () => {
275305

276306
it("should pass valid data to next", async () => {
277307
const action = vi.fn(
278-
async (input: UserInput): Promise<ServerActionResult<TestData>> => {
308+
async (
309+
input: UserInput,
310+
): Promise<ServerActionResult<TestData>> => {
279311
return { ok: true, data: { value: input.name } };
280312
},
281313
);
282314

283-
const validated = withValidation<UserInput, TestData>(validUserSchema);
284-
const result = await validated(action, { name: "John", email: "john@example.com" });
315+
const validated = withZodValidation<UserInput, TestData>(
316+
validUserSchema,
317+
);
318+
const result = await validated(action, {
319+
name: "John",
320+
email: "john@example.com",
321+
});
285322

286323
expect(result).toEqual({ ok: true, data: { value: "John" } });
287-
expect(action).toHaveBeenCalledWith({ name: "John", email: "john@example.com" });
324+
expect(action).toHaveBeenCalledWith({
325+
name: "John",
326+
email: "john@example.com",
327+
});
288328
});
289329

290330
it("should return error for invalid data", async () => {
291331
const action = vi.fn(
292-
async (input: UserInput): Promise<ServerActionResult<TestData>> => {
332+
async (
333+
input: UserInput,
334+
): Promise<ServerActionResult<TestData>> => {
293335
return { ok: true, data: { value: input.name } };
294336
},
295337
);
296338

297-
const validated = withValidation<UserInput, TestData>(validUserSchema);
298-
const result = await validated(action, { name: "", email: "john@example.com" });
339+
const validated = withZodValidation<UserInput, TestData>(
340+
validUserSchema,
341+
);
342+
const result = await validated(action, {
343+
name: "",
344+
email: "john@example.com",
345+
});
299346

300347
expect(result).toEqual({
301348
ok: false,
@@ -307,14 +354,19 @@ describe("middleware", () => {
307354

308355
it("should use custom error code", async () => {
309356
const action = vi.fn(
310-
async (input: UserInput): Promise<ServerActionResult<TestData>> => {
357+
async (
358+
input: UserInput,
359+
): Promise<ServerActionResult<TestData>> => {
311360
return { ok: true, data: { value: input.name } };
312361
},
313362
);
314363

315-
const validated = withValidation<UserInput, TestData>(validUserSchema, {
316-
code: "INVALID_INPUT",
317-
});
364+
const validated = withZodValidation<UserInput, TestData>(
365+
validUserSchema,
366+
{
367+
code: "INVALID_INPUT",
368+
},
369+
);
318370
const result = await validated(action, { name: "", email: "" });
319371

320372
expect(result).toEqual({
@@ -326,14 +378,20 @@ describe("middleware", () => {
326378

327379
it("should use custom error formatter", async () => {
328380
const action = vi.fn(
329-
async (input: UserInput): Promise<ServerActionResult<TestData>> => {
381+
async (
382+
input: UserInput,
383+
): Promise<ServerActionResult<TestData>> => {
330384
return { ok: true, data: { value: input.name } };
331385
},
332386
);
333387

334-
const validated = withValidation<UserInput, TestData>(validUserSchema, {
335-
formatError: (error) => `Custom: ${error.errors?.[0]?.message}`,
336-
});
388+
const validated = withZodValidation<UserInput, TestData>(
389+
validUserSchema,
390+
{
391+
formatError: (error) =>
392+
`Custom: ${error.errors?.[0]?.message}`,
393+
},
394+
);
337395
const result = await validated(action, { name: "", email: "" });
338396

339397
expect(result).toEqual({
@@ -345,24 +403,29 @@ describe("middleware", () => {
345403

346404
it("should work with applyMiddleware", async () => {
347405
const action = vi.fn(
348-
async (input: UserInput): Promise<ServerActionResult<TestData>> => {
406+
async (
407+
input: UserInput,
408+
): Promise<ServerActionResult<TestData>> => {
349409
return { ok: true, data: { value: input.name } };
350410
},
351411
);
352412

353413
const wrappedAction = applyMiddleware(action, [
354-
withValidation(validUserSchema),
414+
withZodValidation(validUserSchema),
355415
]);
356416

357-
const validResult = await wrappedAction({ name: "Jane", email: "jane@test.com" });
417+
const validResult = await wrappedAction({
418+
name: "Jane",
419+
email: "jane@test.com",
420+
});
358421
expect(validResult).toEqual({ ok: true, data: { value: "Jane" } });
359422

360423
const invalidResult = await wrappedAction({ name: "", email: "" });
361424
expect(invalidResult.ok).toBe(false);
362425
});
363426

364427
it("should handle schema with message fallback", async () => {
365-
const schemaWithMessage: ValidationSchema<string> = {
428+
const schemaWithMessage: ValidationZodSchema<string> = {
366429
safeParse: () => ({
367430
success: false,
368431
error: { message: "Schema-level error" },
@@ -375,7 +438,9 @@ describe("middleware", () => {
375438
},
376439
);
377440

378-
const validated = withValidation<string, TestData>(schemaWithMessage);
441+
const validated = withZodValidation<string, TestData>(
442+
schemaWithMessage,
443+
);
379444
const result = await validated(action, "any");
380445

381446
expect(result).toEqual({
@@ -386,7 +451,7 @@ describe("middleware", () => {
386451
});
387452

388453
it("should fallback to default message", async () => {
389-
const schemaWithNoMessage: ValidationSchema<string> = {
454+
const schemaWithNoMessage: ValidationZodSchema<string> = {
390455
safeParse: () => ({
391456
success: false,
392457
error: {},
@@ -399,7 +464,9 @@ describe("middleware", () => {
399464
},
400465
);
401466

402-
const validated = withValidation<string, TestData>(schemaWithNoMessage);
467+
const validated = withZodValidation<string, TestData>(
468+
schemaWithNoMessage,
469+
);
403470
const result = await validated(action, "any");
404471

405472
expect(result).toEqual({
@@ -412,14 +479,19 @@ describe("middleware", () => {
412479

413480
describe("integration", () => {
414481
it("should work with serverAction-style functions", async () => {
415-
const authMiddleware = createMiddleware<[{ token: string }], TestData>(
416-
async (next, params) => {
417-
if (params.token !== "valid") {
418-
return { ok: false, message: "Unauthorized", code: "UNAUTHORIZED" };
419-
}
420-
return next(params);
421-
},
422-
);
482+
const authMiddleware = createMiddleware<
483+
[{ token: string }],
484+
TestData
485+
>(async (next, params) => {
486+
if (params.token !== "valid") {
487+
return {
488+
ok: false,
489+
message: "Unauthorized",
490+
code: "UNAUTHORIZED",
491+
};
492+
}
493+
return next(params);
494+
});
423495

424496
const action = vi.fn(
425497
async (params: {

0 commit comments

Comments
 (0)