balda-js 0.0.1 → 0.0.2

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 (74) hide show
  1. package/lib/cli.d.ts +6 -0
  2. package/lib/cli.js +929 -0
  3. package/lib/cli.js.map +1 -0
  4. package/lib/index.cjs +3384 -0
  5. package/lib/index.cjs.map +1 -0
  6. package/lib/index.d.cts +1492 -0
  7. package/lib/index.d.ts +1492 -0
  8. package/lib/index.js +3327 -0
  9. package/lib/index.js.map +1 -0
  10. package/package.json +1 -1
  11. package/.husky/pre-commit +0 -19
  12. package/.nvmrc +0 -1
  13. package/docs/README.md +0 -135
  14. package/docs/blog/authors.yml +0 -6
  15. package/docs/blog/tags.yml +0 -4
  16. package/docs/cli.md +0 -109
  17. package/docs/docs/core-concepts/controllers.md +0 -393
  18. package/docs/docs/core-concepts/middleware.md +0 -302
  19. package/docs/docs/core-concepts/request-response.md +0 -486
  20. package/docs/docs/core-concepts/routing.md +0 -388
  21. package/docs/docs/core-concepts/server.md +0 -332
  22. package/docs/docs/cron/overview.md +0 -70
  23. package/docs/docs/examples/rest-api.md +0 -595
  24. package/docs/docs/getting-started/configuration.md +0 -168
  25. package/docs/docs/getting-started/installation.md +0 -125
  26. package/docs/docs/getting-started/quick-start.md +0 -273
  27. package/docs/docs/intro.md +0 -46
  28. package/docs/docs/plugins/cookie.md +0 -424
  29. package/docs/docs/plugins/cors.md +0 -295
  30. package/docs/docs/plugins/file.md +0 -382
  31. package/docs/docs/plugins/helmet.md +0 -388
  32. package/docs/docs/plugins/json.md +0 -338
  33. package/docs/docs/plugins/log.md +0 -592
  34. package/docs/docs/plugins/overview.md +0 -390
  35. package/docs/docs/plugins/rate-limiter.md +0 -347
  36. package/docs/docs/plugins/static.md +0 -352
  37. package/docs/docs/plugins/swagger.md +0 -411
  38. package/docs/docs/plugins/urlencoded.md +0 -76
  39. package/docs/docs/testing/examples.md +0 -384
  40. package/docs/docs/testing/mock-server.md +0 -311
  41. package/docs/docs/testing/overview.md +0 -76
  42. package/docs/docusaurus.config.ts +0 -144
  43. package/docs/intro.md +0 -78
  44. package/docs/package.json +0 -46
  45. package/docs/sidebars.ts +0 -72
  46. package/docs/static/.nojekyll +0 -0
  47. package/docs/static/img/docusaurus-social-card.jpg +0 -0
  48. package/docs/static/img/docusaurus.png +0 -0
  49. package/docs/static/img/favicon.ico +0 -0
  50. package/docs/static/img/logo.svg +0 -1
  51. package/docs/static/img/undraw_docusaurus_mountain.svg +0 -37
  52. package/docs/static/img/undraw_docusaurus_react.svg +0 -170
  53. package/docs/static/img/undraw_docusaurus_tree.svg +0 -40
  54. package/docs/tsconfig.json +0 -8
  55. package/speed_test.sh +0 -3
  56. package/test/benchmark/index.ts +0 -17
  57. package/test/cli/cli.ts +0 -7
  58. package/test/commands/test.ts +0 -42
  59. package/test/controllers/file_upload.ts +0 -29
  60. package/test/controllers/urlencoded.ts +0 -13
  61. package/test/controllers/users.ts +0 -111
  62. package/test/cron/index.ts +0 -6
  63. package/test/cron/test_cron.ts +0 -8
  64. package/test/cron/test_cron_imported.ts +0 -8
  65. package/test/native_env.ts +0 -16
  66. package/test/resources/test.txt +0 -1
  67. package/test/server/index.ts +0 -3
  68. package/test/server/instance.ts +0 -63
  69. package/test/suite/upload.test.ts +0 -23
  70. package/test/suite/urlencoded.test.ts +0 -23
  71. package/test/suite/users.test.ts +0 -76
  72. package/todo.md +0 -9
  73. package/tsconfig.json +0 -24
  74. package/vitest.config.ts +0 -17
@@ -1,390 +0,0 @@
1
- ---
2
- sidebar_position: 1
3
- ---
4
-
5
- # Plugins Overview
6
-
7
- Balda.js provides a comprehensive plugin system that allows you to extend the framework's functionality with additional features and middleware.
8
- Those are included by default in the framework as a standard library, you can use them directly or as a reference to create your own plugins.
9
-
10
- ## What are Plugins?
11
-
12
- Plugins in Balda.js are modular components that add specific functionality to your application. They can provide:
13
-
14
- - **Middleware**: Request/response processing
15
- - **Body Parsing**: JSON, form data, file uploads
16
- - **Security**: CORS, Helmet, rate limiting
17
- - **Documentation**: Swagger/OpenAPI
18
- - **Utilities**: Logging, cookies, static file serving
19
-
20
- ## Built-in Plugins
21
-
22
- Balda.js comes with several built-in plugins:
23
-
24
- ### Core Plugins
25
-
26
- - **[CORS](./cors.md)** - Cross-Origin Resource Sharing
27
- - **[JSON](./json.md)** - JSON body parsing
28
- - **[Static](./static.md)** - Static file serving
29
- - **[Cookie](./cookie.md)** - Cookie parsing and management
30
-
31
- ### Security Plugins
32
-
33
- - **[Helmet](./helmet.md)** - Security headers
34
- - **[Rate Limiter](./rate-limiter.md)** - Request rate limiting
35
-
36
- ### Utility Plugins
37
-
38
- - **[Log](./log.md)** - Request logging
39
- - **[File](./file.md)** - File upload handling
40
- - **[URL Encoded](./urlencoded.md)** - Form data parsing
41
-
42
- ### Documentation Plugins
43
-
44
- - **[Swagger](./swagger.md)** - API documentation
45
-
46
- ## Plugin Configuration
47
-
48
- ### Basic Configuration
49
-
50
- Plugins are configured through the server options:
51
-
52
- ```typescript
53
- import { Server } from 'balda-js';
54
-
55
- const server = new Server({
56
- port: 3000,
57
- plugins: {
58
- cors: {
59
- origin: ['http://localhost:3000'],
60
- credentials: true
61
- },
62
- json: {
63
- limit: '10mb'
64
- },
65
- static: {
66
- root: './public'
67
- }
68
- }
69
- });
70
- ```
71
-
72
- ### Environment-based Configuration
73
-
74
- ```typescript
75
- const isProduction = process.env.NODE_ENV === 'production';
76
-
77
- const server = new Server({
78
- port: 3000,
79
- plugins: {
80
- cors: {
81
- origin: isProduction
82
- ? ['https://myapp.com']
83
- : ['http://localhost:3000']
84
- },
85
- helmet: isProduction ? {} : false,
86
- rateLimiter: isProduction ? {
87
- windowMs: 15 * 60 * 1000, // 15 minutes
88
- max: 100 // limit each IP to 100 requests per windowMs
89
- } : false
90
- }
91
- });
92
- ```
93
-
94
- ## Plugin Order
95
-
96
- Plugins are applied in a specific order to ensure proper functionality:
97
-
98
- 1. **CORS** - Handle cross-origin requests first
99
- 2. **Helmet** - Apply security headers
100
- 3. **Rate Limiter** - Check request limits
101
- 4. **Body Parsers** - Parse request bodies
102
- - JSON
103
- - URL Encoded
104
- - File uploads
105
- 5. **Cookie** - Parse cookies
106
- 6. **Log** - Log requests
107
- 7. **Static** - Serve static files
108
- 8. **Swagger** - API documentation
109
-
110
- ## Plugin Options
111
-
112
- ### Enabling/Disabling Plugins
113
-
114
- ```typescript
115
- const server = new Server({
116
- plugins: {
117
- cors: true, // Use default configuration
118
- json: false, // Disable plugin
119
- static: { // Custom configuration
120
- root: './public'
121
- }
122
- }
123
- });
124
- ```
125
-
126
- ### Plugin-specific Options
127
-
128
- Each plugin has its own configuration options:
129
-
130
- ```typescript
131
- const server = new Server({
132
- plugins: {
133
- cors: {
134
- origin: ['http://localhost:3000'],
135
- methods: ['GET', 'POST', 'PUT', 'DELETE'],
136
- credentials: true
137
- },
138
- json: {
139
- limit: '10mb',
140
- strict: true
141
- },
142
- static: {
143
- root: './public',
144
- prefix: '/static'
145
- },
146
- rateLimiter: {
147
- windowMs: 15 * 60 * 1000,
148
- max: 100
149
- }
150
- }
151
- });
152
- ```
153
-
154
- ## Custom Plugins
155
-
156
- ### Creating a Custom Plugin
157
-
158
- ```typescript
159
- import { ServerPlugin } from 'balda-js';
160
-
161
- export class CustomPlugin implements ServerPlugin {
162
- name = 'custom';
163
-
164
- apply(server: Server) {
165
- // Add middleware
166
- server.use((req, res, next) => {
167
- console.log('Custom plugin middleware');
168
- next();
169
- });
170
-
171
- // Add routes
172
- server.get('/custom', (req, res) => {
173
- res.json({ message: 'Custom plugin route' });
174
- });
175
- }
176
- }
177
-
178
- // Usage
179
- const server = new Server({
180
- plugins: {
181
- custom: new CustomPlugin()
182
- }
183
- });
184
- ```
185
-
186
- ### Plugin with Configuration
187
-
188
- ```typescript
189
- interface CustomPluginOptions {
190
- message?: string;
191
- enabled?: boolean;
192
- }
193
-
194
- export class CustomPlugin implements ServerPlugin {
195
- name = 'custom';
196
- private options: CustomPluginOptions;
197
-
198
- constructor(options: CustomPluginOptions = {}) {
199
- this.options = {
200
- message: 'Hello from custom plugin',
201
- enabled: true,
202
- ...options
203
- };
204
- }
205
-
206
- apply(server: Server) {
207
- if (!this.options.enabled) {
208
- return;
209
- }
210
-
211
- server.use((req, res, next) => {
212
- console.log(this.options.message);
213
- next();
214
- });
215
- }
216
- }
217
-
218
- // Usage
219
- const server = new Server({
220
- plugins: {
221
- custom: {
222
- message: 'Custom message',
223
- enabled: true
224
- }
225
- }
226
- });
227
- ```
228
-
229
- ## Plugin Lifecycle
230
-
231
- ### Initialization
232
-
233
- 1. Server creates plugin instances
234
- 2. Plugins are validated
235
- 3. Plugins are applied in order
236
- 4. Middleware is registered
237
-
238
- ### Request Processing
239
-
240
- 1. Request enters plugin middleware chain
241
- 2. Each plugin processes the request
242
- 3. Request reaches route handlers
243
- 4. Response flows back through plugins
244
-
245
- ## Best Practices
246
-
247
- ### 1. Configure Based on Environment
248
-
249
- ```typescript
250
- const isProduction = process.env.NODE_ENV === 'production';
251
-
252
- const server = new Server({
253
- plugins: {
254
- cors: {
255
- origin: isProduction
256
- ? process.env.ALLOWED_ORIGINS?.split(',')
257
- : ['http://localhost:3000'],
258
- credentials: true
259
- },
260
- helmet: isProduction ? {} : false,
261
- rateLimiter: isProduction ? {
262
- windowMs: 15 * 60 * 1000,
263
- max: 100
264
- } : false
265
- }
266
- });
267
- ```
268
-
269
- ### 2. Use Appropriate Limits
270
-
271
- ```typescript
272
- const server = new Server({
273
- plugins: {
274
- json: {
275
- limit: '10mb' // Reasonable limit for JSON payloads
276
- },
277
- file: {
278
- maxFileSize: '5mb', // Limit file uploads
279
- maxFiles: 10
280
- }
281
- }
282
- });
283
- ```
284
-
285
- ### 3. Secure Your Application
286
-
287
- ```typescript
288
- const server = new Server({
289
- plugins: {
290
- helmet: {
291
- contentSecurityPolicy: {
292
- directives: {
293
- defaultSrc: ["'self'"],
294
- styleSrc: ["'self'", "'unsafe-inline'"],
295
- scriptSrc: ["'self'"]
296
- }
297
- }
298
- },
299
- cors: {
300
- origin: ['https://myapp.com'],
301
- credentials: true
302
- }
303
- }
304
- });
305
- ```
306
-
307
- ### 4. Monitor and Log
308
-
309
- ```typescript
310
- const server = new Server({
311
- plugins: {
312
- log: {
313
- level: 'info',
314
- format: 'combined'
315
- },
316
- rateLimiter: {
317
- windowMs: 15 * 60 * 1000,
318
- max: 100,
319
- message: 'Too many requests from this IP'
320
- }
321
- }
322
- });
323
- ```
324
-
325
- ### 5. Optimize for Performance
326
-
327
- ```typescript
328
- const server = new Server({
329
- plugins: {
330
- static: {
331
- root: './public',
332
- maxAge: '1d', // Cache static files
333
- etag: true
334
- },
335
- json: {
336
- limit: '1mb' // Reasonable limit
337
- }
338
- }
339
- });
340
- ```
341
-
342
- ## Plugin Compatibility
343
-
344
- ### Runtime Support
345
-
346
- All built-in plugins work across all supported runtimes:
347
-
348
- - **Node.js**: Full support
349
- - **Bun**: Full support
350
- - **Deno**: Full support
351
-
352
- ### Plugin Dependencies
353
-
354
- Some plugins may have runtime-specific dependencies:
355
-
356
- ```typescript
357
- // Plugin automatically detects runtime and uses appropriate implementation
358
- const server = new Server({
359
- plugins: {
360
- file: {
361
- // Works on Node.js, Bun, and Deno
362
- storage: 'memory' // or 'disk'
363
- }
364
- }
365
- });
366
- ```
367
-
368
- ## Troubleshooting
369
-
370
- ### Common Issues
371
-
372
- 1. **Plugin not working**: Check plugin order and configuration
373
- 2. **CORS errors**: Verify origin configuration
374
- 3. **File upload failures**: Check file size limits and storage configuration
375
- 4. **Rate limiting too strict**: Adjust window and max request settings
376
-
377
- ### Debugging
378
-
379
- Enable debug logging to troubleshoot plugin issues:
380
-
381
- ```typescript
382
- const server = new Server({
383
- debug: true, // Enable debug logging
384
- plugins: {
385
- // Your plugin configuration
386
- }
387
- });
388
- ```
389
-
390
- Plugins in Balda.js provide a powerful and flexible way to extend your application with additional functionality while maintaining clean, modular code.
@@ -1,347 +0,0 @@
1
- ---
2
- sidebar_position: 7
3
- ---
4
-
5
- # Rate Limiter Plugin
6
-
7
- The Rate Limiter plugin helps protect your Balda.js application from abuse by limiting the number of requests a client can make within a specified time window. It supports both IP-based and custom key-based rate limiting with flexible storage options.
8
-
9
- ## Features
10
-
11
- - **IP-Based Limiting**: Limit requests per IP address
12
- - **Custom Key Limiting**: Limit requests based on custom criteria (user ID, API key, etc.)
13
- - **Flexible Storage**: In-memory storage with custom storage support
14
- - **Configurable Limits**: Set custom request limits and time windows
15
- - **Customizable Responses**: Configure error messages and status codes
16
-
17
- ## Basic Configuration
18
-
19
- ### Simple IP-Based Limiting
20
-
21
- ```typescript
22
- import { Server } from 'balda-js';
23
-
24
- const server = new Server({
25
- port: 3000,
26
- plugins: {
27
- rateLimiter: {
28
- type: "ip",
29
- limit: 100,
30
- windowMs: 60000 // 1 minute
31
- }
32
- }
33
- });
34
- ```
35
-
36
- ### Custom Key-Based Limiting
37
-
38
- ```typescript
39
- const server = new Server({
40
- port: 3000,
41
- plugins: {
42
- rateLimiter: {
43
- type: "custom",
44
- key: (req) => req.headers.get('X-API-Key') || req.ip,
45
- limit: 50,
46
- windowMs: 60000
47
- }
48
- }
49
- });
50
- ```
51
-
52
- ## Configuration Options
53
-
54
- ### IP-Based Rate Limiting
55
-
56
- ```typescript
57
- rateLimiter: {
58
- type: "ip",
59
- limit: 100, // Requests per window
60
- windowMs: 60000, // Time window in milliseconds
61
- message: "Too many requests", // Custom error message
62
- statusCode: 429 // Custom status code
63
- }
64
- ```
65
-
66
- ### Custom Key-Based Rate Limiting
67
-
68
- ```typescript
69
- rateLimiter: {
70
- type: "custom",
71
- key: (req) => {
72
- // Custom key generation logic
73
- return req.headers.get('X-API-Key') || req.ip;
74
- },
75
- limit: 50,
76
- windowMs: 60000,
77
- message: "Rate limit exceeded",
78
- statusCode: 429
79
- }
80
- ```
81
-
82
- ### Storage Configuration
83
-
84
- ```typescript
85
- rateLimiter: {
86
- type: "ip",
87
- limit: 100,
88
- windowMs: 60000,
89
- storageStrategy: "memory", // Default: "memory"
90
- // For custom storage:
91
- storageStrategy: "custom",
92
- get: async (key) => { /* custom get logic */ },
93
- set: async (key, value) => { /* custom set logic */ }
94
- }
95
- ```
96
-
97
- ## Usage Examples
98
-
99
- ### Basic Rate Limiting
100
-
101
- ```typescript
102
- const server = new Server({
103
- port: 3000,
104
- plugins: {
105
- rateLimiter: {
106
- type: "ip",
107
- limit: 100,
108
- windowMs: 60000 // 1 minute
109
- }
110
- }
111
- });
112
-
113
- @controller('/api')
114
- export class ApiController {
115
- @get('/users')
116
- async getUsers(req: Request, res: Response) {
117
- // This endpoint is rate limited to 100 requests per minute per IP
118
- const users = await getUsers();
119
- res.json(users);
120
- }
121
- }
122
- ```
123
-
124
- ### Different Limits for Different Endpoints
125
-
126
- ```typescript
127
- @controller('/api')
128
- export class ApiController {
129
- @get('/public', {
130
- middleware: [rateLimiter({
131
- type: "ip",
132
- limit: 1000,
133
- windowMs: 60000
134
- })]
135
- })
136
- async publicEndpoint(req: Request, res: Response) {
137
- // 1000 requests per minute
138
- res.json({ message: 'Public endpoint' });
139
- }
140
-
141
- @get('/sensitive', {
142
- middleware: [rateLimiter({
143
- type: "ip",
144
- limit: 10,
145
- windowMs: 60000
146
- })]
147
- })
148
- async sensitiveEndpoint(req: Request, res: Response) {
149
- // 10 requests per minute
150
- res.json({ message: 'Sensitive endpoint' });
151
- }
152
- }
153
- ```
154
-
155
- ### User-Based Rate Limiting
156
-
157
- ```typescript
158
- @controller('/api')
159
- export class UserController {
160
- @get('/profile', {
161
- middleware: [rateLimiter({
162
- type: "custom",
163
- key: (req) => {
164
- // Rate limit by user ID from JWT token
165
- const token = req.headers.get('Authorization')?.replace('Bearer ', '');
166
- const decoded = jwt.verify(token, process.env.JWT_SECRET);
167
- return decoded.userId;
168
- },
169
- limit: 50,
170
- windowMs: 60000
171
- })]
172
- })
173
- async getProfile(req: Request, res: Response) {
174
- // 50 requests per minute per user
175
- const profile = await getUserProfile(req.user.id);
176
- res.json(profile);
177
- }
178
- }
179
- ```
180
-
181
- ### API Key-Based Rate Limiting
182
-
183
- ```typescript
184
- @controller('/api')
185
- export class ApiKeyController {
186
- @get('/data', {
187
- middleware: [rateLimiter({
188
- type: "custom",
189
- key: (req) => req.headers.get('X-API-Key'),
190
- limit: 1000,
191
- windowMs: 60000
192
- })]
193
- })
194
- async getData(req: Request, res: Response) {
195
- // 1000 requests per minute per API key
196
- const data = await getData();
197
- res.json(data);
198
- }
199
- }
200
- ```
201
-
202
- ## Advanced Configuration
203
-
204
- ### Multiple Rate Limiters
205
-
206
- ```typescript
207
- @controller('/api')
208
- export class AdvancedController {
209
- @get('/complex', {
210
- middleware: [
211
- // IP-based rate limiting
212
- rateLimiter({
213
- type: "ip",
214
- limit: 100,
215
- windowMs: 60000
216
- }),
217
- // User-based rate limiting
218
- rateLimiter({
219
- type: "custom",
220
- key: (req) => req.user?.id || req.ip,
221
- limit: 20,
222
- windowMs: 60000
223
- })
224
- ]
225
- })
226
- async complexEndpoint(req: Request, res: Response) {
227
- // Must pass both rate limiters
228
- res.json({ message: 'Complex endpoint' });
229
- }
230
- }
231
- ```
232
-
233
- ### Custom Storage Implementation
234
-
235
- ```typescript
236
- // Redis storage example
237
- const redisStorage = {
238
- get: async (key: string) => {
239
- const value = await redis.get(`rate_limit:${key}`);
240
- return value ? parseInt(value) : 0;
241
- },
242
- set: async (key: string, value: number) => {
243
- await redis.setex(`rate_limit:${key}`, 60, value.toString());
244
- }
245
- };
246
-
247
- const server = new Server({
248
- port: 3000,
249
- plugins: {
250
- rateLimiter: {
251
- type: "ip",
252
- limit: 100,
253
- windowMs: 60000,
254
- storageStrategy: "custom",
255
- get: redisStorage.get,
256
- set: redisStorage.set
257
- }
258
- }
259
- });
260
- ```
261
-
262
- ### Environment-Based Configuration
263
-
264
- ```typescript
265
- const isProduction = process.env.NODE_ENV === 'production';
266
-
267
- const server = new Server({
268
- port: 3000,
269
- plugins: {
270
- rateLimiter: {
271
- type: "ip",
272
- limit: isProduction ? 100 : 1000, // Stricter in production
273
- windowMs: 60000,
274
- message: isProduction ? "Rate limit exceeded" : "Too many requests",
275
- statusCode: 429
276
- }
277
- }
278
- });
279
- ```
280
-
281
- ## Error Handling
282
-
283
- ### Rate Limit Exceeded Response
284
-
285
- ```typescript
286
- // Default response when rate limit is exceeded
287
- {
288
- "message": "ERR_RATE_LIMIT_EXCEEDED"
289
- }
290
-
291
- // Custom response
292
- {
293
- "message": "Too many requests, please try again later"
294
- }
295
- ```
296
-
297
- ### Custom Error Handling
298
-
299
- ```typescript
300
- @controller('/api')
301
- export class ErrorController {
302
- @get('/limited', {
303
- middleware: [rateLimiter({
304
- type: "ip",
305
- limit: 5,
306
- windowMs: 60000,
307
- message: "You've exceeded the rate limit",
308
- statusCode: 429
309
- })]
310
- })
311
- async limitedEndpoint(req: Request, res: Response) {
312
- res.json({ message: 'Success' });
313
- }
314
- }
315
- ```
316
-
317
- ## Storage Strategies
318
-
319
- ### In-Memory Storage (Default)
320
-
321
- ```typescript
322
- rateLimiter: {
323
- type: "ip",
324
- limit: 100,
325
- windowMs: 60000,
326
- storageStrategy: "memory" // Default
327
- }
328
- ```
329
-
330
- ### Custom Storage
331
-
332
- ```typescript
333
- rateLimiter: {
334
- type: "ip",
335
- limit: 100,
336
- windowMs: 60000,
337
- storageStrategy: "custom",
338
- get: async (key: string) => {
339
- // Custom get implementation
340
- return await yourStorage.get(key);
341
- },
342
- set: async (key: string, value: number) => {
343
- // Custom set implementation
344
- await yourStorage.set(key, value, 60); // 60 seconds TTL
345
- }
346
- }
347
- ```