balda-js 0.0.1

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.
Files changed (69) hide show
  1. package/.github/workflows/publish.yml +38 -0
  2. package/.husky/pre-commit +19 -0
  3. package/.nvmrc +1 -0
  4. package/LICENSE +21 -0
  5. package/README.md +46 -0
  6. package/deno.lock +2454 -0
  7. package/docs/README.md +135 -0
  8. package/docs/blog/authors.yml +6 -0
  9. package/docs/blog/tags.yml +4 -0
  10. package/docs/cli.md +109 -0
  11. package/docs/docs/core-concepts/controllers.md +393 -0
  12. package/docs/docs/core-concepts/middleware.md +302 -0
  13. package/docs/docs/core-concepts/request-response.md +486 -0
  14. package/docs/docs/core-concepts/routing.md +388 -0
  15. package/docs/docs/core-concepts/server.md +332 -0
  16. package/docs/docs/cron/overview.md +70 -0
  17. package/docs/docs/examples/rest-api.md +595 -0
  18. package/docs/docs/getting-started/configuration.md +168 -0
  19. package/docs/docs/getting-started/installation.md +125 -0
  20. package/docs/docs/getting-started/quick-start.md +273 -0
  21. package/docs/docs/intro.md +46 -0
  22. package/docs/docs/plugins/cookie.md +424 -0
  23. package/docs/docs/plugins/cors.md +295 -0
  24. package/docs/docs/plugins/file.md +382 -0
  25. package/docs/docs/plugins/helmet.md +388 -0
  26. package/docs/docs/plugins/json.md +338 -0
  27. package/docs/docs/plugins/log.md +592 -0
  28. package/docs/docs/plugins/overview.md +390 -0
  29. package/docs/docs/plugins/rate-limiter.md +347 -0
  30. package/docs/docs/plugins/static.md +352 -0
  31. package/docs/docs/plugins/swagger.md +411 -0
  32. package/docs/docs/plugins/urlencoded.md +76 -0
  33. package/docs/docs/testing/examples.md +384 -0
  34. package/docs/docs/testing/mock-server.md +311 -0
  35. package/docs/docs/testing/overview.md +76 -0
  36. package/docs/docusaurus.config.ts +144 -0
  37. package/docs/intro.md +78 -0
  38. package/docs/package.json +46 -0
  39. package/docs/sidebars.ts +72 -0
  40. package/docs/static/.nojekyll +0 -0
  41. package/docs/static/img/docusaurus-social-card.jpg +0 -0
  42. package/docs/static/img/docusaurus.png +0 -0
  43. package/docs/static/img/favicon.ico +0 -0
  44. package/docs/static/img/logo.svg +1 -0
  45. package/docs/static/img/undraw_docusaurus_mountain.svg +37 -0
  46. package/docs/static/img/undraw_docusaurus_react.svg +170 -0
  47. package/docs/static/img/undraw_docusaurus_tree.svg +40 -0
  48. package/docs/tsconfig.json +8 -0
  49. package/package.json +91 -0
  50. package/speed_test.sh +3 -0
  51. package/test/benchmark/index.ts +17 -0
  52. package/test/cli/cli.ts +7 -0
  53. package/test/commands/test.ts +42 -0
  54. package/test/controllers/file_upload.ts +29 -0
  55. package/test/controllers/urlencoded.ts +13 -0
  56. package/test/controllers/users.ts +111 -0
  57. package/test/cron/index.ts +6 -0
  58. package/test/cron/test_cron.ts +8 -0
  59. package/test/cron/test_cron_imported.ts +8 -0
  60. package/test/native_env.ts +16 -0
  61. package/test/resources/test.txt +1 -0
  62. package/test/server/index.ts +3 -0
  63. package/test/server/instance.ts +63 -0
  64. package/test/suite/upload.test.ts +23 -0
  65. package/test/suite/urlencoded.test.ts +23 -0
  66. package/test/suite/users.test.ts +76 -0
  67. package/todo.md +9 -0
  68. package/tsconfig.json +24 -0
  69. package/vitest.config.ts +17 -0
@@ -0,0 +1,302 @@
1
+ ---
2
+ sidebar_position: 4
3
+ ---
4
+
5
+ # Middleware
6
+
7
+ Middleware in Balda.js are functions that have access to the request object, response object, and the next middleware function in the application's request-response cycle. They can execute code, modify the request and response objects, end the request-response cycle, and call the next middleware function.
8
+
9
+ ## Basic Middleware
10
+
11
+ ### Function Signature
12
+
13
+ ```typescript
14
+ type Middleware = (
15
+ req: Request,
16
+ res: Response,
17
+ next: NextFunction
18
+ ) => void | Promise<void>;
19
+ ```
20
+
21
+ ### Simple Middleware Example
22
+
23
+ ```typescript
24
+ const logger = (req, res, next) => {
25
+ console.log(`${req.method} ${req.url} - ${new Date().toISOString()}`);
26
+ next();
27
+ };
28
+
29
+ const auth = (req, res, next) => {
30
+ const token = req.headers.authorization;
31
+
32
+ if (!token) {
33
+ return res.unauthorized({ error: 'Authentication required' });
34
+ }
35
+
36
+ // Verify token logic here
37
+ req.user = { id: 1, name: 'John' };
38
+ next();
39
+ };
40
+ ```
41
+
42
+ ## Middleware Application
43
+
44
+ ### Global Middleware
45
+
46
+ Apply middleware to all routes:
47
+
48
+ ```typescript
49
+ import { Server } from 'balda-js';
50
+
51
+ const server = new Server({ port: 3000 });
52
+
53
+ // Apply to all routes
54
+ server.use(logger);
55
+ server.use(cors);
56
+
57
+ // Multiple middleware
58
+ server.use(
59
+ (req, res, next) => {
60
+ req.startTime = Date.now();
61
+ next();
62
+ },
63
+ (req, res, next) => {
64
+ res.on('finish', () => {
65
+ const duration = Date.now() - req.startTime;
66
+ console.log(`${req.method} ${req.url} - ${duration}ms`);
67
+ });
68
+ next();
69
+ }
70
+ );
71
+ ```
72
+
73
+ ### Controller-Level Middleware
74
+
75
+ Apply middleware to all routes in a controller:
76
+
77
+ ```typescript
78
+ import { controller, get, middleware } from 'balda-js';
79
+
80
+ @controller('/users')
81
+ @middleware(authMiddleware)
82
+ export class UsersController {
83
+ @get('/')
84
+ async getAllUsers(req, res) {
85
+ // This route will use authMiddleware
86
+ res.json({ users: [] });
87
+ }
88
+
89
+ @get('/public')
90
+ @middleware(publicMiddleware) // Override controller middleware
91
+ async getPublicUsers(req, res) {
92
+ // This route will use publicMiddleware instead
93
+ res.json({ users: [] });
94
+ }
95
+ }
96
+ ```
97
+
98
+ ### Route-Level Middleware
99
+
100
+ Apply middleware to specific routes:
101
+
102
+ ```typescript
103
+ @get('/admin/users', { middleware: [authMiddleware, adminMiddleware] })
104
+ async getAdminUsers(req, res) {
105
+ res.json({ users: [] });
106
+ }
107
+ ```
108
+
109
+ ## Common Middleware Patterns
110
+
111
+ ### Authentication Middleware
112
+
113
+ ```typescript
114
+ const authMiddleware = async (req, res, next) => {
115
+ const token = req.headers.authorization?.replace('Bearer ', '');
116
+
117
+ if (!token) {
118
+ return res.unauthorized({ error: 'Authentication token required' });
119
+ }
120
+
121
+ try {
122
+ // Verify JWT token
123
+ const decoded = jwt.verify(token, process.env.JWT_SECRET);
124
+ req.user = decoded;
125
+ next();
126
+ } catch (error) {
127
+ return res.unauthorized({ error: 'Invalid authentication token' });
128
+ }
129
+ };
130
+ ```
131
+
132
+ ### Role-Based Authorization
133
+
134
+ ```typescript
135
+ const requireRole = (role) => {
136
+ return (req, res, next) => {
137
+ if (!req.user) {
138
+ return res.unauthorized({ error: 'Authentication required' });
139
+ }
140
+
141
+ if (req.user.role !== role) {
142
+ return res.forbidden({ error: 'Insufficient permissions' });
143
+ }
144
+
145
+ next();
146
+ };
147
+ };
148
+
149
+ // Usage
150
+ @get('/admin', { middleware: [authMiddleware, requireRole('admin')] })
151
+ async getAdminPanel(req, res) {
152
+ res.json({ admin: true });
153
+ }
154
+ ```
155
+
156
+ ### Request Logging
157
+
158
+ ```typescript
159
+ const requestLogger = (req, res, next) => {
160
+ const start = Date.now();
161
+
162
+ res.on('finish', () => {
163
+ const duration = Date.now() - start;
164
+ console.log(`${req.method} ${req.url} ${res.statusCode} - ${duration}ms`);
165
+ });
166
+
167
+ next();
168
+ };
169
+ ```
170
+
171
+ ### Error Handling Middleware
172
+
173
+ ```typescript
174
+ const errorHandler = (req, res, next, error) => {
175
+ console.error('Error:', error);
176
+
177
+ if (error.name === 'ValidationError') {
178
+ return res.badRequest({ error: error.message });
179
+ }
180
+
181
+ if (error.name === 'UnauthorizedError') {
182
+ return res.unauthorized({ error: 'Authentication required' });
183
+ }
184
+
185
+ res.internalServerError({ error: 'Internal server error' });
186
+ };
187
+
188
+ server.setErrorHandler(errorHandler);
189
+ ```
190
+
191
+ ### CORS Middleware
192
+
193
+ ```typescript
194
+ const corsMiddleware = (req, res, next) => {
195
+ res.setHeader('Access-Control-Allow-Origin', '*');
196
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
197
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
198
+
199
+ if (req.method === 'OPTIONS') {
200
+ res.status(200).end();
201
+ return;
202
+ }
203
+
204
+ next();
205
+ };
206
+ ```
207
+
208
+ ### Rate Limiting
209
+
210
+ ```typescript
211
+ const rateLimit = (windowMs = 15 * 60 * 1000, max = 100) => {
212
+ const requests = new Map();
213
+
214
+ return (req, res, next) => {
215
+ const ip = req.ip;
216
+ const now = Date.now();
217
+
218
+ if (!requests.has(ip)) {
219
+ requests.set(ip, { count: 0, resetTime: now + windowMs });
220
+ }
221
+
222
+ const record = requests.get(ip);
223
+
224
+ if (now > record.resetTime) {
225
+ record.count = 0;
226
+ record.resetTime = now + windowMs;
227
+ }
228
+
229
+ if (record.count >= max) {
230
+ return res.tooManyRequests({ error: 'Too many requests' });
231
+ }
232
+
233
+ record.count++;
234
+ next();
235
+ };
236
+ };
237
+ ```
238
+
239
+ ## Middleware Order
240
+
241
+ The order of middleware matters. Middleware are executed in the order they are applied:
242
+
243
+ ```typescript
244
+ // 1. Global middleware (applied first)
245
+ server.use(logger);
246
+ server.use(cors);
247
+
248
+ // 2. Controller middleware
249
+ @controller('/users')
250
+ @middleware(authMiddleware) // Applied to all routes in controller
251
+
252
+ // 3. Route middleware (applied last)
253
+ @get('/admin', { middleware: [adminMiddleware] })
254
+ async getAdmin(req, res) {
255
+ // Execution order: logger -> cors -> authMiddleware -> adminMiddleware -> handler
256
+ }
257
+ ```
258
+
259
+ ## Async Middleware
260
+
261
+ Middleware can be async functions:
262
+
263
+ ```typescript
264
+ const asyncAuthMiddleware = async (req, res, next) => {
265
+ try {
266
+ const token = req.headers.authorization?.replace('Bearer ', '');
267
+
268
+ if (!token) {
269
+ return res.unauthorized({ error: 'Authentication required' });
270
+ }
271
+
272
+ // Async operation
273
+ const user = await verifyToken(token);
274
+ req.user = user;
275
+ next();
276
+ } catch (error) {
277
+ return res.unauthorized({ error: 'Invalid token' });
278
+ }
279
+ };
280
+ ```
281
+
282
+ ## Conditional Middleware
283
+
284
+ Apply middleware conditionally:
285
+
286
+ ```typescript
287
+ const conditionalAuth = (req, res, next) => {
288
+ // Skip auth for public routes
289
+ if (req.path.startsWith('/public')) {
290
+ return next();
291
+ }
292
+
293
+ // Apply auth for protected routes
294
+ const token = req.headers.authorization;
295
+ if (!token) {
296
+ return res.unauthorized({ error: 'Authentication required' });
297
+ }
298
+
299
+ req.user = { id: 1 };
300
+ next();
301
+ };
302
+ ```