superstruct-express
v1.0.0
Published
Type-Safe Express Middleware for Superstruct Data Validation Library
Downloads
3
Maintainers
Readme
superstruct-express
Type-Safe Express Middleware for Superstruct Data Validation Library
Installation
npm i superstruct-express
yarn add superstruct-express
pnpm add superstruct-express
superstruct-express
requires both superstruct
and express
as peer dependency installed.
If you are about to setup a new project from scratch, use the following command:
npm i express superstruct superstruct-express
yarn add express superstruct superstruct-express
pnpm add express superstruct superstruct-express
Example
superstruct-express
exports an extension to the plain express Router
supporting full type-safety. From there you can simply register your desired express routes with superstruct
validators via the ValidatedRequest
middleware.
import {
TypedRouter,
ValidatedRequest,
ValidationErrorHandler,
} from 'superstruct-express'
import { literal, number, object, type, string } from 'superstruct'
const router = TypedRouter()
const validator = type({
query: object({
populated: optional(literal('true')),
}),
param: object({
userId: string(),
}),
})
router.get(
'/my/api/users',
ValidatedRequest(
validator,
async (_, { query: { populated }, param: { userId } }, res) => {
// here <populated> is of type boolean | undefined and <userId> of type string
const user = await getUserFromDB(userId, populated)
res.json(user).end()
}
)
)
Custom Error Handler
ValidatedRequest
supports as a third argument a custom error handler.
import {
ValidatedRequest,
ValidationErrorHandler,
ValidationErrorHandler,
} from 'superstruct-express'
const customErrorHandler: ValidationErrorHandler<Express.Request> = (
req,
error,
res
) => {
// typeof error = StructError
console.error(error)
// do whatever you want with the error and return it in some way as request response
res.status(400).send(error.toString())
}
router.get(
'/my/api/users',
ValidatedRequest(
validator,
async (_, { query: { populated }, param: { userId } }, res) => {
// here <populated> is of type boolean | undefined and <userId> of type string
const user = await getUserFromDB(userId, populated)
res.json(user).end()
},
customErrorHandler
)
)
Pre-Checked Router Context
TypedRouter
supports a router context via generics. This can be useful if you register a router-wide middleware, e.g. some authentication middleware.
interface AuthenticatedRouter {
user: User
}
const rootRouter = TypedRouter()
rootRouter.use(myAuthMiddleware) // middleware checks authentication and sets req.user property if successful
const router = TypedRouter<AuthenticatedRouter>()
rootRouter.use(router)
const validator = type({
query: object({
populated: optional(literal('true')),
}),
})
router.get(
'/my/api/orders',
ValidatedRequest(
validator,
async ({ user }, { query: { populated }, param: { userId } }, res) => {
// here we can consume the context properties - in this case the <user> property
const orders = await getOrdersOfUser(user.id, populated)
res.json(orders).end()
}
)
)
License
MIT