@noony-serverless/core 0.1.5 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/core/core.d.ts +16 -48
- package/build/core/core.js +2 -61
- package/build/core/handler.d.ts +37 -16
- package/build/core/handler.js +131 -42
- package/build/core/index.d.ts +0 -1
- package/build/core/index.js +0 -1
- package/build/middlewares/ConsolidatedValidationMiddleware.d.ts +126 -0
- package/build/middlewares/ConsolidatedValidationMiddleware.js +330 -0
- package/build/middlewares/ProcessingMiddleware.d.ts +138 -0
- package/build/middlewares/ProcessingMiddleware.js +425 -0
- package/build/middlewares/SecurityMiddleware.d.ts +157 -0
- package/build/middlewares/SecurityMiddleware.js +307 -0
- package/build/middlewares/bodyValidationMiddleware.d.ts +12 -10
- package/build/middlewares/bodyValidationMiddleware.js +10 -8
- package/build/middlewares/guards/RouteGuards.d.ts +239 -4
- package/build/middlewares/guards/RouteGuards.js +301 -8
- package/build/middlewares/guards/adapters/CustomTokenVerificationPortAdapter.d.ts +271 -0
- package/build/middlewares/guards/adapters/CustomTokenVerificationPortAdapter.js +301 -0
- package/build/middlewares/guards/config/GuardConfiguration.d.ts +50 -0
- package/build/middlewares/guards/config/GuardConfiguration.js +59 -0
- package/build/middlewares/guards/guards/FastAuthGuard.d.ts +5 -5
- package/build/middlewares/guards/guards/PermissionGuardFactory.d.ts +5 -13
- package/build/middlewares/guards/guards/PermissionGuardFactory.js +4 -4
- package/build/middlewares/guards/index.d.ts +43 -1
- package/build/middlewares/guards/index.js +46 -1
- package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.js +1 -1
- package/build/middlewares/guards/resolvers/PermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/PlainPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/WildcardPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/services/FastUserContextService.d.ts +20 -33
- package/build/middlewares/guards/services/FastUserContextService.js +17 -4
- package/build/middlewares/httpAttributesMiddleware.js +1 -1
- package/build/middlewares/index.d.ts +3 -1
- package/build/middlewares/index.js +6 -1
- package/build/middlewares/rateLimitingMiddleware.d.ts +492 -4
- package/build/middlewares/rateLimitingMiddleware.js +514 -6
- package/package.json +11 -9
- package/build/core/containerPool.d.ts +0 -44
- package/build/core/containerPool.js +0 -103
- package/build/middlewares/validationMiddleware.d.ts +0 -154
- package/build/middlewares/validationMiddleware.js +0 -185
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.containerPool = exports.ContainerPool = void 0;
|
|
7
|
-
const typedi_1 = __importDefault(require("typedi"));
|
|
8
|
-
/**
|
|
9
|
-
* Performance optimization: Container Pool for reusing TypeDI containers
|
|
10
|
-
* This reduces object creation overhead and improves memory efficiency
|
|
11
|
-
*/
|
|
12
|
-
class ContainerPool {
|
|
13
|
-
availableContainers = [];
|
|
14
|
-
maxPoolSize = 10;
|
|
15
|
-
createdContainers = 0;
|
|
16
|
-
constructor(maxPoolSize = 10) {
|
|
17
|
-
this.maxPoolSize = maxPoolSize;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Get a container from the pool or create a new one
|
|
21
|
-
*/
|
|
22
|
-
acquire() {
|
|
23
|
-
if (this.availableContainers.length > 0) {
|
|
24
|
-
return this.availableContainers.pop();
|
|
25
|
-
}
|
|
26
|
-
// Create new container if pool is empty and under limit
|
|
27
|
-
if (this.createdContainers < this.maxPoolSize) {
|
|
28
|
-
this.createdContainers++;
|
|
29
|
-
return typedi_1.default.of();
|
|
30
|
-
}
|
|
31
|
-
// If pool is at capacity, create a temporary container
|
|
32
|
-
// This should rarely happen in normal usage
|
|
33
|
-
return typedi_1.default.of();
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Return a container to the pool for reuse
|
|
37
|
-
*/
|
|
38
|
-
release(container) {
|
|
39
|
-
if (this.availableContainers.length < this.maxPoolSize) {
|
|
40
|
-
// Reset container state by removing all instances
|
|
41
|
-
// This prevents memory leaks and cross-request contamination
|
|
42
|
-
this.resetContainer(container);
|
|
43
|
-
this.availableContainers.push(container);
|
|
44
|
-
}
|
|
45
|
-
// If pool is full, let the container be garbage collected
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Reset container state to prevent cross-request contamination
|
|
49
|
-
* Note: TypeDI containers are isolated by default, so we mainly need
|
|
50
|
-
* to clear any manually set values
|
|
51
|
-
*/
|
|
52
|
-
resetContainer(_container) {
|
|
53
|
-
try {
|
|
54
|
-
// For TypeDI containers created with Container.of(), each container
|
|
55
|
-
// is already isolated. We just need to ensure no memory leaks.
|
|
56
|
-
// The container will be garbage collected when released from pool
|
|
57
|
-
// if it contains too much data
|
|
58
|
-
// TypeDI containers are self-contained and don't need explicit reset
|
|
59
|
-
// This is a placeholder for future enhancements if needed
|
|
60
|
-
}
|
|
61
|
-
catch (error) {
|
|
62
|
-
// If any issues occur, don't add back to pool
|
|
63
|
-
console.warn('Failed to reset container, discarding:', error);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Get pool statistics for monitoring
|
|
68
|
-
*/
|
|
69
|
-
getStats() {
|
|
70
|
-
return {
|
|
71
|
-
available: this.availableContainers.length,
|
|
72
|
-
created: this.createdContainers,
|
|
73
|
-
maxSize: this.maxPoolSize,
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Warm up the pool by pre-creating containers
|
|
78
|
-
*/
|
|
79
|
-
warmUp(count = 5) {
|
|
80
|
-
const warmUpCount = Math.min(count, this.maxPoolSize);
|
|
81
|
-
for (let i = 0; i < warmUpCount; i++) {
|
|
82
|
-
if (this.createdContainers < this.maxPoolSize) {
|
|
83
|
-
const container = typedi_1.default.of();
|
|
84
|
-
this.createdContainers++;
|
|
85
|
-
this.availableContainers.push(container);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Clear all containers from the pool
|
|
91
|
-
*/
|
|
92
|
-
clear() {
|
|
93
|
-
this.availableContainers = [];
|
|
94
|
-
this.createdContainers = 0;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
exports.ContainerPool = ContainerPool;
|
|
98
|
-
// Global container pool instance
|
|
99
|
-
const containerPool = new ContainerPool(15); // Slightly higher limit for serverless
|
|
100
|
-
exports.containerPool = containerPool;
|
|
101
|
-
// Warm up the pool for better cold start performance
|
|
102
|
-
containerPool.warmUp(3);
|
|
103
|
-
//# sourceMappingURL=containerPool.js.map
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
import { BaseMiddleware, Context } from '../core';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
/**
|
|
4
|
-
* Middleware class that validates request data (body or query parameters) using Zod schemas.
|
|
5
|
-
* Automatically detects GET requests and validates query parameters, or validates body for other methods.
|
|
6
|
-
*
|
|
7
|
-
* @implements {BaseMiddleware}
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* User registration validation:
|
|
11
|
-
* ```typescript
|
|
12
|
-
* import { z } from 'zod';
|
|
13
|
-
* import { Handler, ValidationMiddleware } from '@noony-serverless/core';
|
|
14
|
-
*
|
|
15
|
-
* const userRegistrationSchema = z.object({
|
|
16
|
-
* email: z.string().email(),
|
|
17
|
-
* password: z.string().min(8),
|
|
18
|
-
* firstName: z.string().min(1),
|
|
19
|
-
* lastName: z.string().min(1),
|
|
20
|
-
* age: z.number().int().min(18).max(120)
|
|
21
|
-
* });
|
|
22
|
-
*
|
|
23
|
-
* const registerHandler = new Handler()
|
|
24
|
-
* .use(bodyParser())
|
|
25
|
-
* .use(new ValidationMiddleware(userRegistrationSchema))
|
|
26
|
-
* .handle(async (context) => {
|
|
27
|
-
* const validatedUser = context.req.validatedBody;
|
|
28
|
-
* const newUser = await createUser(validatedUser);
|
|
29
|
-
* return { success: true, userId: newUser.id };
|
|
30
|
-
* });
|
|
31
|
-
* ```
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
* GET request query parameter validation:
|
|
35
|
-
* ```typescript
|
|
36
|
-
* const searchSchema = z.object({
|
|
37
|
-
* q: z.string().min(1),
|
|
38
|
-
* page: z.string().regex(/^\d+$/).transform(Number).default('1'),
|
|
39
|
-
* limit: z.string().regex(/^\d+$/).transform(Number).default('10'),
|
|
40
|
-
* category: z.string().optional()
|
|
41
|
-
* });
|
|
42
|
-
*
|
|
43
|
-
* const searchHandler = new Handler()
|
|
44
|
-
* .use(new ValidationMiddleware(searchSchema))
|
|
45
|
-
* .handle(async (context) => {
|
|
46
|
-
* const { q, page, limit, category } = context.req.query;
|
|
47
|
-
* const results = await searchItems(q, { page, limit, category });
|
|
48
|
-
* return { success: true, results, query: { q, page, limit, category } };
|
|
49
|
-
* });
|
|
50
|
-
* ```
|
|
51
|
-
*
|
|
52
|
-
* @example
|
|
53
|
-
* Product creation with nested validation:
|
|
54
|
-
* ```typescript
|
|
55
|
-
* const productSchema = z.object({
|
|
56
|
-
* name: z.string().min(1).max(100),
|
|
57
|
-
* description: z.string().max(1000),
|
|
58
|
-
* price: z.number().positive(),
|
|
59
|
-
* category: z.enum(['electronics', 'clothing', 'books', 'home']),
|
|
60
|
-
* specifications: z.record(z.string()),
|
|
61
|
-
* images: z.array(z.string().url()).max(5),
|
|
62
|
-
* inventory: z.object({
|
|
63
|
-
* inStock: z.boolean(),
|
|
64
|
-
* quantity: z.number().int().min(0),
|
|
65
|
-
* warehouse: z.string()
|
|
66
|
-
* })
|
|
67
|
-
* });
|
|
68
|
-
*
|
|
69
|
-
* const createProductHandler = new Handler()
|
|
70
|
-
* .use(bodyParser())
|
|
71
|
-
* .use(new ValidationMiddleware(productSchema))
|
|
72
|
-
* .handle(async (context) => {
|
|
73
|
-
* const productData = context.req.validatedBody;
|
|
74
|
-
* const product = await createProduct(productData);
|
|
75
|
-
* return { success: true, productId: product.id };
|
|
76
|
-
* });
|
|
77
|
-
* ```
|
|
78
|
-
*/
|
|
79
|
-
export declare class ValidationMiddleware implements BaseMiddleware {
|
|
80
|
-
private readonly schema;
|
|
81
|
-
constructor(schema: z.ZodSchema);
|
|
82
|
-
before(context: Context): Promise<void>;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Factory function that creates a validation middleware using Zod schema.
|
|
86
|
-
* Automatically validates request body for non-GET requests or query parameters for GET requests.
|
|
87
|
-
*
|
|
88
|
-
* @param schema - Zod schema to validate against
|
|
89
|
-
* @returns BaseMiddleware object with validation logic
|
|
90
|
-
*
|
|
91
|
-
* @example
|
|
92
|
-
* Login endpoint validation:
|
|
93
|
-
* ```typescript
|
|
94
|
-
* import { z } from 'zod';
|
|
95
|
-
* import { Handler, validationMiddleware } from '@noony-serverless/core';
|
|
96
|
-
*
|
|
97
|
-
* const loginSchema = z.object({
|
|
98
|
-
* email: z.string().email(),
|
|
99
|
-
* password: z.string().min(1),
|
|
100
|
-
* rememberMe: z.boolean().optional()
|
|
101
|
-
* });
|
|
102
|
-
*
|
|
103
|
-
* const loginHandler = new Handler()
|
|
104
|
-
* .use(bodyParser())
|
|
105
|
-
* .use(validationMiddleware(loginSchema))
|
|
106
|
-
* .handle(async (context) => {
|
|
107
|
-
* const { email, password, rememberMe } = context.req.validatedBody;
|
|
108
|
-
* const token = await authenticate(email, password);
|
|
109
|
-
* return { success: true, token, rememberMe };
|
|
110
|
-
* });
|
|
111
|
-
* ```
|
|
112
|
-
*
|
|
113
|
-
* @example
|
|
114
|
-
* API filtering with query validation:
|
|
115
|
-
* ```typescript
|
|
116
|
-
* const filterSchema = z.object({
|
|
117
|
-
* status: z.enum(['active', 'inactive', 'pending']).optional(),
|
|
118
|
-
* sort: z.enum(['name', 'date', 'status']).default('name'),
|
|
119
|
-
* order: z.enum(['asc', 'desc']).default('asc'),
|
|
120
|
-
* limit: z.coerce.number().int().min(1).max(100).default(10)
|
|
121
|
-
* });
|
|
122
|
-
*
|
|
123
|
-
* const getItemsHandler = new Handler()
|
|
124
|
-
* .use(validationMiddleware(filterSchema))
|
|
125
|
-
* .handle(async (context) => {
|
|
126
|
-
* const filters = context.req.query;
|
|
127
|
-
* const items = await getFilteredItems(filters);
|
|
128
|
-
* return { success: true, items, appliedFilters: filters };
|
|
129
|
-
* });
|
|
130
|
-
* ```
|
|
131
|
-
*
|
|
132
|
-
* @example
|
|
133
|
-
* File upload validation:
|
|
134
|
-
* ```typescript
|
|
135
|
-
* const uploadSchema = z.object({
|
|
136
|
-
* filename: z.string().min(1),
|
|
137
|
-
* mimeType: z.string().regex(/^(image|document)\//),
|
|
138
|
-
* size: z.number().max(10 * 1024 * 1024), // 10MB max
|
|
139
|
-
* description: z.string().max(200).optional(),
|
|
140
|
-
* tags: z.array(z.string()).max(10).optional()
|
|
141
|
-
* });
|
|
142
|
-
*
|
|
143
|
-
* const uploadHandler = new Handler()
|
|
144
|
-
* .use(bodyParser())
|
|
145
|
-
* .use(validationMiddleware(uploadSchema))
|
|
146
|
-
* .handle(async (context) => {
|
|
147
|
-
* const fileData = context.req.validatedBody;
|
|
148
|
-
* const upload = await processFileUpload(fileData);
|
|
149
|
-
* return { success: true, fileId: upload.id };
|
|
150
|
-
* });
|
|
151
|
-
* ```
|
|
152
|
-
*/
|
|
153
|
-
export declare const validationMiddleware: (schema: z.ZodSchema) => BaseMiddleware;
|
|
154
|
-
//# sourceMappingURL=validationMiddleware.d.ts.map
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.validationMiddleware = exports.ValidationMiddleware = void 0;
|
|
4
|
-
const core_1 = require("../core");
|
|
5
|
-
const zod_1 = require("zod");
|
|
6
|
-
const validate = async (schema, context) => {
|
|
7
|
-
try {
|
|
8
|
-
const data = context.req.method === 'GET' ? context.req.query : context.req.parsedBody;
|
|
9
|
-
const validated = await schema.parseAsync(data);
|
|
10
|
-
if (context.req.method === 'GET') {
|
|
11
|
-
context.req.query = validated;
|
|
12
|
-
}
|
|
13
|
-
else {
|
|
14
|
-
context.req.validatedBody = validated;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
catch (error) {
|
|
18
|
-
if (error instanceof zod_1.z.ZodError) {
|
|
19
|
-
throw new core_1.ValidationError('Validation error', JSON.stringify(error.errors));
|
|
20
|
-
}
|
|
21
|
-
throw error;
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
/**
|
|
25
|
-
* Middleware class that validates request data (body or query parameters) using Zod schemas.
|
|
26
|
-
* Automatically detects GET requests and validates query parameters, or validates body for other methods.
|
|
27
|
-
*
|
|
28
|
-
* @implements {BaseMiddleware}
|
|
29
|
-
*
|
|
30
|
-
* @example
|
|
31
|
-
* User registration validation:
|
|
32
|
-
* ```typescript
|
|
33
|
-
* import { z } from 'zod';
|
|
34
|
-
* import { Handler, ValidationMiddleware } from '@noony-serverless/core';
|
|
35
|
-
*
|
|
36
|
-
* const userRegistrationSchema = z.object({
|
|
37
|
-
* email: z.string().email(),
|
|
38
|
-
* password: z.string().min(8),
|
|
39
|
-
* firstName: z.string().min(1),
|
|
40
|
-
* lastName: z.string().min(1),
|
|
41
|
-
* age: z.number().int().min(18).max(120)
|
|
42
|
-
* });
|
|
43
|
-
*
|
|
44
|
-
* const registerHandler = new Handler()
|
|
45
|
-
* .use(bodyParser())
|
|
46
|
-
* .use(new ValidationMiddleware(userRegistrationSchema))
|
|
47
|
-
* .handle(async (context) => {
|
|
48
|
-
* const validatedUser = context.req.validatedBody;
|
|
49
|
-
* const newUser = await createUser(validatedUser);
|
|
50
|
-
* return { success: true, userId: newUser.id };
|
|
51
|
-
* });
|
|
52
|
-
* ```
|
|
53
|
-
*
|
|
54
|
-
* @example
|
|
55
|
-
* GET request query parameter validation:
|
|
56
|
-
* ```typescript
|
|
57
|
-
* const searchSchema = z.object({
|
|
58
|
-
* q: z.string().min(1),
|
|
59
|
-
* page: z.string().regex(/^\d+$/).transform(Number).default('1'),
|
|
60
|
-
* limit: z.string().regex(/^\d+$/).transform(Number).default('10'),
|
|
61
|
-
* category: z.string().optional()
|
|
62
|
-
* });
|
|
63
|
-
*
|
|
64
|
-
* const searchHandler = new Handler()
|
|
65
|
-
* .use(new ValidationMiddleware(searchSchema))
|
|
66
|
-
* .handle(async (context) => {
|
|
67
|
-
* const { q, page, limit, category } = context.req.query;
|
|
68
|
-
* const results = await searchItems(q, { page, limit, category });
|
|
69
|
-
* return { success: true, results, query: { q, page, limit, category } };
|
|
70
|
-
* });
|
|
71
|
-
* ```
|
|
72
|
-
*
|
|
73
|
-
* @example
|
|
74
|
-
* Product creation with nested validation:
|
|
75
|
-
* ```typescript
|
|
76
|
-
* const productSchema = z.object({
|
|
77
|
-
* name: z.string().min(1).max(100),
|
|
78
|
-
* description: z.string().max(1000),
|
|
79
|
-
* price: z.number().positive(),
|
|
80
|
-
* category: z.enum(['electronics', 'clothing', 'books', 'home']),
|
|
81
|
-
* specifications: z.record(z.string()),
|
|
82
|
-
* images: z.array(z.string().url()).max(5),
|
|
83
|
-
* inventory: z.object({
|
|
84
|
-
* inStock: z.boolean(),
|
|
85
|
-
* quantity: z.number().int().min(0),
|
|
86
|
-
* warehouse: z.string()
|
|
87
|
-
* })
|
|
88
|
-
* });
|
|
89
|
-
*
|
|
90
|
-
* const createProductHandler = new Handler()
|
|
91
|
-
* .use(bodyParser())
|
|
92
|
-
* .use(new ValidationMiddleware(productSchema))
|
|
93
|
-
* .handle(async (context) => {
|
|
94
|
-
* const productData = context.req.validatedBody;
|
|
95
|
-
* const product = await createProduct(productData);
|
|
96
|
-
* return { success: true, productId: product.id };
|
|
97
|
-
* });
|
|
98
|
-
* ```
|
|
99
|
-
*/
|
|
100
|
-
class ValidationMiddleware {
|
|
101
|
-
schema;
|
|
102
|
-
constructor(schema) {
|
|
103
|
-
this.schema = schema;
|
|
104
|
-
}
|
|
105
|
-
async before(context) {
|
|
106
|
-
await validate(this.schema, context);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
exports.ValidationMiddleware = ValidationMiddleware;
|
|
110
|
-
/**
|
|
111
|
-
* Factory function that creates a validation middleware using Zod schema.
|
|
112
|
-
* Automatically validates request body for non-GET requests or query parameters for GET requests.
|
|
113
|
-
*
|
|
114
|
-
* @param schema - Zod schema to validate against
|
|
115
|
-
* @returns BaseMiddleware object with validation logic
|
|
116
|
-
*
|
|
117
|
-
* @example
|
|
118
|
-
* Login endpoint validation:
|
|
119
|
-
* ```typescript
|
|
120
|
-
* import { z } from 'zod';
|
|
121
|
-
* import { Handler, validationMiddleware } from '@noony-serverless/core';
|
|
122
|
-
*
|
|
123
|
-
* const loginSchema = z.object({
|
|
124
|
-
* email: z.string().email(),
|
|
125
|
-
* password: z.string().min(1),
|
|
126
|
-
* rememberMe: z.boolean().optional()
|
|
127
|
-
* });
|
|
128
|
-
*
|
|
129
|
-
* const loginHandler = new Handler()
|
|
130
|
-
* .use(bodyParser())
|
|
131
|
-
* .use(validationMiddleware(loginSchema))
|
|
132
|
-
* .handle(async (context) => {
|
|
133
|
-
* const { email, password, rememberMe } = context.req.validatedBody;
|
|
134
|
-
* const token = await authenticate(email, password);
|
|
135
|
-
* return { success: true, token, rememberMe };
|
|
136
|
-
* });
|
|
137
|
-
* ```
|
|
138
|
-
*
|
|
139
|
-
* @example
|
|
140
|
-
* API filtering with query validation:
|
|
141
|
-
* ```typescript
|
|
142
|
-
* const filterSchema = z.object({
|
|
143
|
-
* status: z.enum(['active', 'inactive', 'pending']).optional(),
|
|
144
|
-
* sort: z.enum(['name', 'date', 'status']).default('name'),
|
|
145
|
-
* order: z.enum(['asc', 'desc']).default('asc'),
|
|
146
|
-
* limit: z.coerce.number().int().min(1).max(100).default(10)
|
|
147
|
-
* });
|
|
148
|
-
*
|
|
149
|
-
* const getItemsHandler = new Handler()
|
|
150
|
-
* .use(validationMiddleware(filterSchema))
|
|
151
|
-
* .handle(async (context) => {
|
|
152
|
-
* const filters = context.req.query;
|
|
153
|
-
* const items = await getFilteredItems(filters);
|
|
154
|
-
* return { success: true, items, appliedFilters: filters };
|
|
155
|
-
* });
|
|
156
|
-
* ```
|
|
157
|
-
*
|
|
158
|
-
* @example
|
|
159
|
-
* File upload validation:
|
|
160
|
-
* ```typescript
|
|
161
|
-
* const uploadSchema = z.object({
|
|
162
|
-
* filename: z.string().min(1),
|
|
163
|
-
* mimeType: z.string().regex(/^(image|document)\//),
|
|
164
|
-
* size: z.number().max(10 * 1024 * 1024), // 10MB max
|
|
165
|
-
* description: z.string().max(200).optional(),
|
|
166
|
-
* tags: z.array(z.string()).max(10).optional()
|
|
167
|
-
* });
|
|
168
|
-
*
|
|
169
|
-
* const uploadHandler = new Handler()
|
|
170
|
-
* .use(bodyParser())
|
|
171
|
-
* .use(validationMiddleware(uploadSchema))
|
|
172
|
-
* .handle(async (context) => {
|
|
173
|
-
* const fileData = context.req.validatedBody;
|
|
174
|
-
* const upload = await processFileUpload(fileData);
|
|
175
|
-
* return { success: true, fileId: upload.id };
|
|
176
|
-
* });
|
|
177
|
-
* ```
|
|
178
|
-
*/
|
|
179
|
-
const validationMiddleware = (schema) => ({
|
|
180
|
-
before: async (context) => {
|
|
181
|
-
await validate(schema, context);
|
|
182
|
-
},
|
|
183
|
-
});
|
|
184
|
-
exports.validationMiddleware = validationMiddleware;
|
|
185
|
-
//# sourceMappingURL=validationMiddleware.js.map
|