SpaceNode
SpaceNode has a built-in validation system with array-based rules. You can also plug in Zod, Joi, or Yup via adapters.
// modules/auth/auth.dto.js
import { dto } from 'SpaceNode'
export const loginDto = dto({
email: ['string', 'required', 'email'],
password: ['string', 'required', 'min:6'],
})
export const registerDto = dto({
name: ['string', 'required', 'min:2', 'max:50'],
email: ['string', 'required', 'email'],
password: ['string', 'required', 'min:6'],
role: ['string', 'enum:customer,seller', 'default:customer'],
})
routes: [
['POST', '/login', 'login', ['dto:loginDto']],
['POST', '/register', 'register', ['dto:registerDto']],
]
The dto:loginDto pipe validates request.body against the schema. If validation fails, it throws a ValidationError (400) with detailed error messages. If it passes, request.body is replaced with the cleaned output.
| Rule | Description |
|---|---|
string | Must be a string |
number | Must be a number (not NaN) |
boolean | Must be a boolean |
array | Must be an array |
object | Must be a non-null, non-array object |
email | Must be a valid email format |
url | Must start with http:// or https:// |
uuid | Must be a valid UUID |
date | Must be parseable by Date.parse() |
required | Field cannot be undefined, null or empty string |
optional | Field is optional (default behavior) |
min:N | Min length (string/array) or min value (number) |
max:N | Max length (string/array) or max value (number) |
length:N | Exact length (string/array) |
pattern:REGEX | Must match the regex pattern |
enum:a,b,c | Must be one of the listed values |
default:VALUE | Use this value if field is missing |
export const createOrderDto = dto({
productId: ['string', 'required'],
quantity: ['number', 'required', 'min:1'],
shipping: {
address: ['string', 'required'],
city: ['string', 'required'],
zip: ['string', 'required', 'pattern:^\\d{5}$'],
},
})
export const myDto = dto({
age: (value) => {
if (typeof value !== 'number' || value < 18) return 'Must be 18+'
return true
},
})
import { registerAdapter } from 'SpaceNode'
import { z } from 'zod'
// Register Zod adapter once
registerAdapter('zod', (schema, data) => {
const result = schema.safeParse(data)
if (!result.success) return { errors: result.error.issues }
return { output: result.data }
})
// Use in DTO files
export const loginDto = {
adapter: 'zod',
schema: z.object({
email: z.string().email(),
password: z.string().min(6),
}),
}
// POST /auth/login with invalid body
// Response 400:
{
"error": "Validation failed",
"status": 400,
"details": [
{ "field": "email", "message": "email must be a valid email" },
{ "field": "password", "message": "password failed min:6 check" }
]
}