@noony-serverless/core
Version:
A Middy base framework compatible with Firebase and GCP Cloud Functions with TypeScript
158 lines • 5.65 kB
TypeScript
import { BaseMiddleware, Context } from '../core';
import { z } from 'zod';
/**
* Middleware class that validates request data (body or query parameters) using Zod schemas.
* Automatically detects GET requests and validates query parameters, or validates body for other methods.
*
* @template TBody - The type of the request body payload (preserves type chain)
* @template TUser - The type of the authenticated user (preserves type chain)
* @implements {BaseMiddleware<TBody, TUser>}
*
* @example
* User registration validation:
* ```typescript
* import { z } from 'zod';
* import { Handler, ValidationMiddleware } from '@noony-serverless/core';
*
* const userRegistrationSchema = z.object({
* email: z.string().email(),
* password: z.string().min(8),
* firstName: z.string().min(1),
* lastName: z.string().min(1),
* age: z.number().int().min(18).max(120)
* });
*
* const registerHandler = new Handler()
* .use(bodyParser())
* .use(new ValidationMiddleware(userRegistrationSchema))
* .handle(async (context) => {
* const validatedUser = context.req.validatedBody;
* const newUser = await createUser(validatedUser);
* return { success: true, userId: newUser.id };
* });
* ```
*
* @example
* GET request query parameter validation:
* ```typescript
* const searchSchema = z.object({
* q: z.string().min(1),
* page: z.string().regex(/^\d+$/).transform(Number).default('1'),
* limit: z.string().regex(/^\d+$/).transform(Number).default('10'),
* category: z.string().optional()
* });
*
* const searchHandler = new Handler()
* .use(new ValidationMiddleware(searchSchema))
* .handle(async (context) => {
* const { q, page, limit, category } = context.req.query;
* const results = await searchItems(q, { page, limit, category });
* return { success: true, results, query: { q, page, limit, category } };
* });
* ```
*
* @example
* Product creation with nested validation:
* ```typescript
* const productSchema = z.object({
* name: z.string().min(1).max(100),
* description: z.string().max(1000),
* price: z.number().positive(),
* category: z.enum(['electronics', 'clothing', 'books', 'home']),
* specifications: z.record(z.string()),
* images: z.array(z.string().url()).max(5),
* inventory: z.object({
* inStock: z.boolean(),
* quantity: z.number().int().min(0),
* warehouse: z.string()
* })
* });
*
* const createProductHandler = new Handler()
* .use(bodyParser())
* .use(new ValidationMiddleware(productSchema))
* .handle(async (context) => {
* const productData = context.req.validatedBody;
* const product = await createProduct(productData);
* return { success: true, productId: product.id };
* });
* ```
*/
export declare class ValidationMiddleware<TBody = unknown, TUser = unknown> implements BaseMiddleware<TBody, TUser> {
private readonly schema;
constructor(schema: z.ZodSchema);
before(context: Context<TBody, TUser>): Promise<void>;
}
/**
* Factory function that creates a validation middleware using Zod schema.
* Automatically validates request body for non-GET requests or query parameters for GET requests.
*
* @template TBody - The type of the request body payload (preserves type chain)
* @template TUser - The type of the authenticated user (preserves type chain)
* @param schema - Zod schema to validate against
* @returns BaseMiddleware object with validation logic
*
* @example
* Login endpoint validation:
* ```typescript
* import { z } from 'zod';
* import { Handler, validationMiddleware } from '@noony-serverless/core';
*
* const loginSchema = z.object({
* email: z.string().email(),
* password: z.string().min(1),
* rememberMe: z.boolean().optional()
* });
*
* const loginHandler = new Handler()
* .use(bodyParser())
* .use(validationMiddleware(loginSchema))
* .handle(async (context) => {
* const { email, password, rememberMe } = context.req.validatedBody;
* const token = await authenticate(email, password);
* return { success: true, token, rememberMe };
* });
* ```
*
* @example
* API filtering with query validation:
* ```typescript
* const filterSchema = z.object({
* status: z.enum(['active', 'inactive', 'pending']).optional(),
* sort: z.enum(['name', 'date', 'status']).default('name'),
* order: z.enum(['asc', 'desc']).default('asc'),
* limit: z.coerce.number().int().min(1).max(100).default(10)
* });
*
* const getItemsHandler = new Handler()
* .use(validationMiddleware(filterSchema))
* .handle(async (context) => {
* const filters = context.req.query;
* const items = await getFilteredItems(filters);
* return { success: true, items, appliedFilters: filters };
* });
* ```
*
* @example
* File upload validation:
* ```typescript
* const uploadSchema = z.object({
* filename: z.string().min(1),
* mimeType: z.string().regex(/^(image|document)\//),
* size: z.number().max(10 * 1024 * 1024), // 10MB max
* description: z.string().max(200).optional(),
* tags: z.array(z.string()).max(10).optional()
* });
*
* const uploadHandler = new Handler()
* .use(bodyParser())
* .use(validationMiddleware(uploadSchema))
* .handle(async (context) => {
* const fileData = context.req.validatedBody;
* const upload = await processFileUpload(fileData);
* return { success: true, fileId: upload.id };
* });
* ```
*/
export declare const validationMiddleware: <TBody = unknown, TUser = unknown>(schema: z.ZodSchema) => BaseMiddleware<TBody, TUser>;
//# sourceMappingURL=validationMiddleware.d.ts.map