Skip to content

Commit e3b73e8

Browse files
📚 docs(Validation): Validation docs improvements with new functions and new response structure
1 parent 466a242 commit e3b73e8

2 files changed

Lines changed: 90 additions & 118 deletions

File tree

docs/endpoints/data-validation-old.md

Lines changed: 0 additions & 106 deletions
This file was deleted.

docs/endpoints/data-validation.md

Lines changed: 90 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ import { Yelix, requestDataValidationYelixMiddleware } from 'jsr:@murat/yelix';
1515

1616
export async function startServer() {
1717
const app = new Yelix();
18-
19-
// Load your endpoints here
20-
2118
app.setMiddleware('dataValidation', requestDataValidationYelixMiddleware);
2219
app.serve();
2320
}
@@ -30,22 +27,67 @@ await startServer();
3027
```ts title="hello.ts"
3128
import { Ctx, ValidationType, inp } from "jsr:@murat/yelix";
3229

33-
export async function GET(ctx: Ctx) {
30+
export async function POST(ctx: Ctx) {
3431
const requestData = ctx.get('dataValidation').user;
35-
const { name } = requestData.query;
36-
return await ctx.text(`Hello, ${name}!`, 200);
32+
const { username, email } = requestData.body;
33+
return await ctx.text(`Hello, ${username}!`, 200);
3734
}
3835

3936
export const path = '/api/hello';
4037
export const middlewares = ['dataValidation'];
4138

4239
export const validation: ValidationType = {
43-
query: {
44-
name: inp().string().min(3).max(255)
45-
}
40+
body: inp().object({
41+
username: inp().string().min(3).max(255),
42+
email: inp().string().email()
43+
})
4644
};
4745
```
4846

47+
<details>
48+
<summary>
49+
**Failed Response**
50+
</summary>
51+
52+
The response structure is designed to be easily consumable by front-end applications. It presents validation errors in a clear, structured format, grouping errors by field and providing detailed messages for each validation rule that failed.
53+
54+
```json
55+
{
56+
"errors": {
57+
"username": [
58+
{
59+
"message": "This field must be a string and is required.",
60+
"key": "username",
61+
"from": "body"
62+
},
63+
{
64+
"message": "String must be at least 3 characters long",
65+
"key": "username",
66+
"from": "body"
67+
},
68+
{
69+
"message": "String must be at most 255 characters long",
70+
"key": "username",
71+
"from": "body"
72+
}
73+
],
74+
"email": [
75+
{
76+
"message": "This field must be a string and is required.",
77+
"key": "email",
78+
"from": "body"
79+
},
80+
{
81+
"message": "Invalid email address",
82+
"key": "email",
83+
"from": "body"
84+
}
85+
]
86+
}
87+
}
88+
```
89+
</details>
90+
4991
## Available Validators
5092

5193
### String Validation
@@ -69,6 +111,8 @@ inp().string()
69111
.datetime() // ISO datetime format
70112
.base64() // Base64 string
71113
.optional() // Make field optional
114+
.enum(["admin", "user"]) // Must be one of values
115+
.toNumber() // Convert to number (useful for query params)
72116
```
73117

74118
### Number Validation
@@ -84,6 +128,7 @@ inp().number()
84128
.finite() // Must be finite
85129
.safe() // Safe integer
86130
.optional() // Make field optional
131+
.enum([1, 2, 3, 5]) // Must be one of values
87132
```
88133

89134
### Array Validation
@@ -137,6 +182,7 @@ inp().date()
137182
.weekday([1,2,3,4,5]) // Valid weekdays
138183
.age(18) // Minimum age
139184
.optional() // Make field optional
185+
.enum([new Date("2024-01-01"), new Date("2024-12-31")]) // Must be one of dates
140186
```
141187

142188
### File Validation
@@ -209,14 +255,46 @@ export const validation: ValidationType = {
209255
};
210256
```
211257

258+
## Things To Consider
259+
260+
#### Number validation in query
261+
262+
When validating numbers in query parameters, you can use the `toNumber()` method to convert the string to a number. This is useful for cases where you expect a number but receive it as a string in the query.
263+
264+
```ts
265+
inp()
266+
.string()
267+
.toNumber() // Convert string to number but float is allowed
268+
.integer() // Only allow integers
269+
.min(1) // Minimum value
270+
```
271+
272+
#### Validation Context Differences (query, body, formData)
273+
274+
Understanding how validation works across different contexts is crucial:
275+
276+
- **query**: Uses direct object notation for URL parameters
277+
- **body**: Requires `inp().object()` wrapper since it handles JSON payloads
278+
- **formData**: Uses direct object notation for form data fields
279+
280+
```ts
281+
export const validation: ValidationType = {
282+
query: {},
283+
// highlight-next-line
284+
body: inp().object({ }),
285+
formData: {}
286+
}
287+
```
288+
212289
## Complete Example
213290

214291
```ts
215292
export const validation: ValidationType = {
216293
query: {
217-
page: inp().number().integer().min(1).optional(),
218-
limit: inp().number().integer().range(1, 100),
219-
isActive: inp().boolean().transform() // Accepts "true", "1", true, etc.
294+
page: inp().string().toNumber().integer().min(1).optional(),
295+
limit: inp().string().toNumber().integer().range(1, 100),
296+
type: inp().string().enum(["user", "admin", "guest"]),
297+
userId: inp().string().toNumber().enum([1, 2, 3, 4, 5])
220298
},
221299
body: inp().object({
222300
username: inp().string().min(3).max(255),

0 commit comments

Comments
 (0)