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,388 @@
1
+ ---
2
+ sidebar_position: 6
3
+ ---
4
+
5
+ # Helmet Plugin
6
+
7
+ The Helmet plugin sets various HTTP headers to help protect your Balda.js application from well-known web vulnerabilities. It's a security middleware that helps secure your app by setting several HTTP headers.
8
+
9
+ ## Features
10
+
11
+ - **Security Headers**: Sets various security-related HTTP headers
12
+ - **Configurable Options**: Customize which headers to enable/disable
13
+ - **Production Ready**: Optimized security settings for production
14
+ - **Easy Integration**: Simple configuration with sensible defaults
15
+ - **Comprehensive Protection**: Covers multiple attack vectors
16
+
17
+ ## Basic Configuration
18
+
19
+ ### Simple Setup
20
+
21
+ ```typescript
22
+ import { Server } from 'balda-js';
23
+
24
+ const server = new Server({
25
+ port: 3000,
26
+ plugins: {
27
+ helmet: {}
28
+ }
29
+ });
30
+ ```
31
+
32
+ ### Disable Helmet
33
+
34
+ ```typescript
35
+ const server = new Server({
36
+ port: 3000,
37
+ plugins: {
38
+ helmet: false
39
+ }
40
+ });
41
+ ```
42
+
43
+ ## Configuration Options
44
+
45
+ ### Default Configuration
46
+
47
+ ```typescript
48
+ helmet: {
49
+ dnsPrefetchControl: true,
50
+ frameguard: { action: "SAMEORIGIN" },
51
+ hsts: { maxAge: 15552000, includeSubDomains: true, preload: false },
52
+ contentTypeOptions: true,
53
+ ieNoOpen: true,
54
+ xssFilter: true,
55
+ referrerPolicy: "no-referrer",
56
+ crossOriginResourcePolicy: "same-origin",
57
+ crossOriginOpenerPolicy: "same-origin",
58
+ crossOriginEmbedderPolicy: "require-corp",
59
+ contentSecurityPolicy: false
60
+ }
61
+ ```
62
+
63
+ ### Custom Configuration
64
+
65
+ ```typescript
66
+ const server = new Server({
67
+ port: 3000,
68
+ plugins: {
69
+ helmet: {
70
+ contentSecurityPolicy: {
71
+ directives: {
72
+ defaultSrc: ["'self'"],
73
+ styleSrc: ["'self'", "'unsafe-inline'"],
74
+ scriptSrc: ["'self'"],
75
+ imgSrc: ["'self'", "data:", "https:"]
76
+ }
77
+ },
78
+ hsts: {
79
+ maxAge: 31536000, // 1 year
80
+ includeSubDomains: true,
81
+ preload: true
82
+ }
83
+ }
84
+ }
85
+ });
86
+ ```
87
+
88
+ ## Security Headers Explained
89
+
90
+ ### Content Security Policy (CSP)
91
+
92
+ ```typescript
93
+ helmet: {
94
+ contentSecurityPolicy: {
95
+ directives: {
96
+ defaultSrc: ["'self'"],
97
+ styleSrc: ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com"],
98
+ scriptSrc: ["'self'", "https://cdn.jsdelivr.net"],
99
+ imgSrc: ["'self'", "data:", "https:"],
100
+ fontSrc: ["'self'", "https://fonts.gstatic.com"],
101
+ connectSrc: ["'self'", "https://api.example.com"],
102
+ frameSrc: ["'none'"],
103
+ objectSrc: ["'none'"],
104
+ mediaSrc: ["'self'"],
105
+ manifestSrc: ["'self'"]
106
+ }
107
+ }
108
+ }
109
+ ```
110
+
111
+ ### HTTP Strict Transport Security (HSTS)
112
+
113
+ ```typescript
114
+ helmet: {
115
+ hsts: {
116
+ maxAge: 31536000, // 1 year
117
+ includeSubDomains: true, // Apply to subdomains
118
+ preload: true // Include in browser preload lists
119
+ }
120
+ }
121
+ ```
122
+
123
+ ### Frame Options
124
+
125
+ ```typescript
126
+ helmet: {
127
+ frameguard: {
128
+ action: "DENY" // Prevent embedding in frames
129
+ }
130
+ }
131
+
132
+ // Or use string values
133
+ helmet: {
134
+ frameguard: "DENY" // Same as above
135
+ }
136
+ ```
137
+
138
+ ### XSS Protection
139
+
140
+ ```typescript
141
+ helmet: {
142
+ xssFilter: true // Enable XSS protection
143
+ }
144
+ ```
145
+
146
+ ### Content Type Options
147
+
148
+ ```typescript
149
+ helmet: {
150
+ contentTypeOptions: true // Prevent MIME type sniffing
151
+ }
152
+ ```
153
+
154
+ ## Usage Examples
155
+
156
+ ### Basic Security Setup
157
+
158
+ ```typescript
159
+ const server = new Server({
160
+ port: 3000,
161
+ plugins: {
162
+ helmet: {
163
+ contentSecurityPolicy: false, // Disable CSP for development
164
+ hsts: false // Disable HSTS for HTTP
165
+ }
166
+ }
167
+ });
168
+ ```
169
+
170
+ ### Production Security Configuration
171
+
172
+ ```typescript
173
+ const isProduction = process.env.NODE_ENV === 'production';
174
+
175
+ const server = new Server({
176
+ port: 3000,
177
+ plugins: {
178
+ helmet: {
179
+ contentSecurityPolicy: isProduction ? {
180
+ directives: {
181
+ defaultSrc: ["'self'"],
182
+ styleSrc: ["'self'", "'unsafe-inline'"],
183
+ scriptSrc: ["'self'"],
184
+ imgSrc: ["'self'", "data:", "https:"],
185
+ fontSrc: ["'self'", "https://fonts.gstatic.com"],
186
+ connectSrc: ["'self'"],
187
+ frameSrc: ["'none'"],
188
+ objectSrc: ["'none'"]
189
+ }
190
+ } : false,
191
+ hsts: isProduction ? {
192
+ maxAge: 31536000,
193
+ includeSubDomains: true,
194
+ preload: true
195
+ } : false,
196
+ frameguard: { action: "DENY" },
197
+ xssFilter: true,
198
+ contentTypeOptions: true,
199
+ referrerPolicy: "strict-origin-when-cross-origin"
200
+ }
201
+ }
202
+ });
203
+ ```
204
+
205
+ ### API-Focused Configuration
206
+
207
+ ```typescript
208
+ const server = new Server({
209
+ port: 3000,
210
+ plugins: {
211
+ helmet: {
212
+ contentSecurityPolicy: false, // APIs don't need CSP
213
+ hsts: {
214
+ maxAge: 31536000,
215
+ includeSubDomains: true
216
+ },
217
+ frameguard: { action: "DENY" },
218
+ xssFilter: true,
219
+ contentTypeOptions: true,
220
+ referrerPolicy: "no-referrer"
221
+ }
222
+ }
223
+ });
224
+ ```
225
+
226
+ ### Web Application Configuration
227
+
228
+ ```typescript
229
+ const server = new Server({
230
+ port: 3000,
231
+ plugins: {
232
+ helmet: {
233
+ contentSecurityPolicy: {
234
+ directives: {
235
+ defaultSrc: ["'self'"],
236
+ styleSrc: ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com"],
237
+ scriptSrc: ["'self'", "https://cdn.jsdelivr.net"],
238
+ imgSrc: ["'self'", "data:", "https:"],
239
+ fontSrc: ["'self'", "https://fonts.gstatic.com"],
240
+ connectSrc: ["'self'", "wss:"],
241
+ frameSrc: ["'self'"],
242
+ objectSrc: ["'none'"],
243
+ mediaSrc: ["'self'"],
244
+ manifestSrc: ["'self'"]
245
+ }
246
+ },
247
+ hsts: {
248
+ maxAge: 31536000,
249
+ includeSubDomains: true,
250
+ preload: true
251
+ },
252
+ frameguard: { action: "SAMEORIGIN" },
253
+ xssFilter: true,
254
+ contentTypeOptions: true,
255
+ referrerPolicy: "strict-origin-when-cross-origin"
256
+ }
257
+ }
258
+ });
259
+ ```
260
+
261
+ ## Individual Header Configuration
262
+
263
+ ### DNS Prefetch Control
264
+
265
+ ```typescript
266
+ helmet: {
267
+ dnsPrefetchControl: true // Disable DNS prefetching
268
+ }
269
+ ```
270
+
271
+ ### Frame Guard
272
+
273
+ ```typescript
274
+ helmet: {
275
+ frameguard: {
276
+ action: "DENY" // Prevent all framing
277
+ }
278
+ }
279
+
280
+ // Available actions:
281
+ // "DENY" - Prevent all framing
282
+ // "SAMEORIGIN" - Allow same-origin framing
283
+ // "ALLOW-FROM uri" - Allow framing from specific URI
284
+ ```
285
+
286
+ ### HSTS Configuration
287
+
288
+ ```typescript
289
+ helmet: {
290
+ hsts: {
291
+ maxAge: 31536000, // Time in seconds
292
+ includeSubDomains: true, // Apply to subdomains
293
+ preload: true // Include in preload lists
294
+ }
295
+ }
296
+ ```
297
+
298
+ ### Content Type Options
299
+
300
+ ```typescript
301
+ helmet: {
302
+ contentTypeOptions: true // Prevent MIME type sniffing
303
+ }
304
+ ```
305
+
306
+ ### IE No Open
307
+
308
+ ```typescript
309
+ helmet: {
310
+ ieNoOpen: true // Prevent IE from executing downloads
311
+ }
312
+ ```
313
+
314
+ ### XSS Filter
315
+
316
+ ```typescript
317
+ helmet: {
318
+ xssFilter: true // Enable XSS protection
319
+ }
320
+ ```
321
+
322
+ ### Referrer Policy
323
+
324
+ ```typescript
325
+ helmet: {
326
+ referrerPolicy: "strict-origin-when-cross-origin"
327
+ }
328
+
329
+ // Available policies:
330
+ // "no-referrer"
331
+ // "no-referrer-when-downgrade"
332
+ // "origin"
333
+ // "origin-when-cross-origin"
334
+ // "same-origin"
335
+ // "strict-origin"
336
+ // "strict-origin-when-cross-origin"
337
+ // "unsafe-url"
338
+ ```
339
+
340
+ ### Cross-Origin Policies
341
+
342
+ ```typescript
343
+ helmet: {
344
+ crossOriginResourcePolicy: "same-origin",
345
+ crossOriginOpenerPolicy: "same-origin",
346
+ crossOriginEmbedderPolicy: "require-corp"
347
+ }
348
+ ```
349
+
350
+ ## Environment-Based Configuration
351
+
352
+ ### Development vs Production
353
+
354
+ ```typescript
355
+ const isProduction = process.env.NODE_ENV === 'production';
356
+
357
+ const helmetConfig = isProduction ? {
358
+ contentSecurityPolicy: {
359
+ directives: {
360
+ defaultSrc: ["'self'"],
361
+ styleSrc: ["'self'", "'unsafe-inline'"],
362
+ scriptSrc: ["'self'"],
363
+ imgSrc: ["'self'", "data:", "https:"]
364
+ }
365
+ },
366
+ hsts: {
367
+ maxAge: 31536000,
368
+ includeSubDomains: true,
369
+ preload: true
370
+ },
371
+ frameguard: { action: "DENY" },
372
+ xssFilter: true,
373
+ contentTypeOptions: true
374
+ } : {
375
+ contentSecurityPolicy: false,
376
+ hsts: false,
377
+ frameguard: { action: "SAMEORIGIN" },
378
+ xssFilter: true,
379
+ contentTypeOptions: true
380
+ };
381
+
382
+ const server = new Server({
383
+ port: 3000,
384
+ plugins: {
385
+ helmet: helmetConfig
386
+ }
387
+ });
388
+ ```
@@ -0,0 +1,338 @@
1
+ ---
2
+ sidebar_position: 3
3
+ ---
4
+
5
+ # JSON Plugin
6
+
7
+ The JSON plugin parses incoming JSON request bodies and populates `req.body` with the parsed data. It automatically handles content-type detection and provides configurable size limits and error handling.
8
+
9
+ ## Features
10
+
11
+ - **Automatic Content-Type Detection**: Parses requests with `application/json` content type
12
+ - **Configurable Size Limits**: Set maximum body size to prevent memory issues
13
+ - **Encoding Support**: Support for various text encodings
14
+ - **Error Handling**: Graceful handling of malformed JSON
15
+ - **Empty Body Handling**: Configurable behavior for empty request bodies
16
+
17
+ ## Basic Configuration
18
+
19
+ ### Simple Setup
20
+
21
+ ```typescript
22
+ import { Server } from 'balda-js';
23
+
24
+ const server = new Server({
25
+ port: 3000,
26
+ plugins: {
27
+ json: {
28
+ sizeLimit: '10mb'
29
+ }
30
+ }
31
+ });
32
+ ```
33
+
34
+ ### Default Configuration
35
+
36
+ ```typescript
37
+ const server = new Server({
38
+ port: 3000,
39
+ plugins: {
40
+ json: {
41
+ sizeLimit: 5 * 1024 * 1024, // 5MB
42
+ parseEmptyBodyAsObject: false,
43
+ encoding: 'utf-8'
44
+ }
45
+ }
46
+ });
47
+ ```
48
+
49
+ ## Configuration Options
50
+
51
+ ### Size Limit
52
+
53
+ ```typescript
54
+ // Using bytes
55
+ json: {
56
+ sizeLimit: 1024 * 1024 // 1MB
57
+ }
58
+
59
+ // Using string notation
60
+ json: {
61
+ sizeLimit: '10mb'
62
+ }
63
+
64
+ // Large payloads
65
+ json: {
66
+ sizeLimit: 50 * 1024 * 1024 // 50MB
67
+ }
68
+ ```
69
+
70
+ ### Empty Body Handling
71
+
72
+ ```typescript
73
+ // Default behavior - empty body becomes undefined
74
+ json: {
75
+ parseEmptyBodyAsObject: false
76
+ }
77
+
78
+ // Empty body becomes empty object
79
+ json: {
80
+ parseEmptyBodyAsObject: true
81
+ }
82
+ ```
83
+
84
+ ### Custom Error Messages
85
+
86
+ ```typescript
87
+ json: {
88
+ sizeLimit: '10mb',
89
+ customErrorMessage: {
90
+ status: 413,
91
+ message: 'Request body too large'
92
+ }
93
+ }
94
+ ```
95
+
96
+ ### Encoding Configuration
97
+
98
+ ```typescript
99
+ // UTF-8 (default)
100
+ json: {
101
+ encoding: 'utf-8'
102
+ }
103
+
104
+ // UTF-16
105
+ json: {
106
+ encoding: 'utf-16le'
107
+ }
108
+
109
+ // Other encodings
110
+ json: {
111
+ encoding: 'iso-8859-1'
112
+ }
113
+ ```
114
+
115
+ ## Usage Examples
116
+
117
+ ### Basic JSON Parsing
118
+
119
+ ```typescript
120
+ @controller('/api')
121
+ export class ApiController {
122
+ @post('/users')
123
+ async createUser(req: Request, res: Response) {
124
+ // req.body is automatically parsed JSON
125
+ const { name, email, age } = req.body;
126
+
127
+ const user = await createUser({ name, email, age });
128
+ res.created(user);
129
+ }
130
+ }
131
+ ```
132
+
133
+ ### Handling Large Payloads
134
+
135
+ ```typescript
136
+ const server = new Server({
137
+ port: 3000,
138
+ plugins: {
139
+ json: {
140
+ sizeLimit: '50mb', // Allow large file uploads
141
+ customErrorMessage: {
142
+ status: 413,
143
+ message: 'File too large'
144
+ }
145
+ }
146
+ }
147
+ });
148
+
149
+ @controller('/api')
150
+ export class FileController {
151
+ @post('/upload')
152
+ async uploadFile(req: Request, res: Response) {
153
+ // Handle large JSON payloads
154
+ const fileData = req.body;
155
+ res.json({ message: 'File uploaded successfully' });
156
+ }
157
+ }
158
+ ```
159
+
160
+ ### Empty Body Scenarios
161
+
162
+ ```typescript
163
+ @controller('/api')
164
+ export class HealthController {
165
+ @post('/health')
166
+ async healthCheck(req: Request, res: Response) {
167
+ if (req.body === undefined) {
168
+ // Empty body with parseEmptyBodyAsObject: false
169
+ res.json({ status: 'ok', body: 'empty' });
170
+ } else if (Object.keys(req.body).length === 0) {
171
+ // Empty body with parseEmptyBodyAsObject: true
172
+ res.json({ status: 'ok', body: 'empty object' });
173
+ } else {
174
+ res.json({ status: 'ok', body: req.body });
175
+ }
176
+ }
177
+ }
178
+ ```
179
+
180
+ ## Error Handling
181
+
182
+ ### Size Limit Exceeded
183
+
184
+ ```typescript
185
+ // Request with body larger than sizeLimit
186
+ // Response: 413 Payload Too Large
187
+ {
188
+ "error": "ERR_REQUEST_BODY_TOO_LARGE"
189
+ }
190
+
191
+ // With custom error message
192
+ {
193
+ "error": "Request body too large"
194
+ }
195
+ ```
196
+
197
+ ### Invalid JSON
198
+
199
+ ```typescript
200
+ // Request with malformed JSON
201
+ // POST /api/users
202
+ // Content-Type: application/json
203
+ // Body: { "name": "John", "email": "john@example.com" }
204
+
205
+ // Response: 400 Bad Request
206
+ {
207
+ "error": "Invalid JSON syntax"
208
+ }
209
+ ```
210
+
211
+ ### Invalid Encoding
212
+
213
+ ```typescript
214
+ // Request with unsupported encoding
215
+ // Response: 400 Bad Request
216
+ {
217
+ "error": "Invalid request body encoding"
218
+ }
219
+ ```
220
+
221
+ ## Content-Type Detection
222
+
223
+ The JSON plugin automatically detects and parses requests with the following content types:
224
+
225
+ - `application/json`
226
+ - `application/json; charset=utf-8`
227
+ - `application/json; charset=UTF-8`
228
+
229
+ ### Non-JSON Requests
230
+
231
+ Requests without `application/json` content type are ignored:
232
+
233
+ ```typescript
234
+ // This request will NOT be parsed by the JSON plugin
235
+ // POST /api/users
236
+ // Content-Type: application/x-www-form-urlencoded
237
+ // Body: name=John&email=john@example.com
238
+
239
+ @post('/users')
240
+ async createUser(req: Request, res: Response) {
241
+ // req.body will be undefined or handled by another parser
242
+ console.log(req.body); // undefined
243
+ }
244
+ ```
245
+
246
+ ## HTTP Method Restrictions
247
+
248
+ The JSON plugin only parses bodies for methods that can have a body:
249
+
250
+ - **Parsed**: POST, PUT, PATCH
251
+ - **Ignored**: GET, DELETE, HEAD, OPTIONS
252
+
253
+ ```typescript
254
+ @controller('/api')
255
+ export class UsersController {
256
+ @get('/users')
257
+ async getUsers(req: Request, res: Response) {
258
+ // req.body will be undefined (GET request)
259
+ res.json({ users: [] });
260
+ }
261
+
262
+ @post('/users')
263
+ async createUser(req: Request, res: Response) {
264
+ // req.body will be parsed JSON
265
+ res.created(req.body);
266
+ }
267
+ }
268
+ ```
269
+
270
+ ## Advanced Configuration
271
+
272
+ ### Production vs Development
273
+
274
+ ```typescript
275
+ const isProduction = process.env.NODE_ENV === 'production';
276
+
277
+ const server = new Server({
278
+ port: 3000,
279
+ plugins: {
280
+ json: {
281
+ sizeLimit: isProduction ? '1mb' : '10mb',
282
+ parseEmptyBodyAsObject: false,
283
+ encoding: 'utf-8',
284
+ customErrorMessage: isProduction ? {
285
+ status: 413,
286
+ message: 'Request too large'
287
+ } : undefined
288
+ }
289
+ }
290
+ });
291
+ ```
292
+
293
+ ### Multiple Content Types
294
+
295
+ ```typescript
296
+ // JSON plugin handles application/json
297
+ // URL-encoded plugin handles application/x-www-form-urlencoded
298
+ const server = new Server({
299
+ port: 3000,
300
+ plugins: {
301
+ json: {
302
+ sizeLimit: '10mb'
303
+ },
304
+ urlencoded: {
305
+ extended: true
306
+ }
307
+ }
308
+ });
309
+ ```
310
+
311
+ ## Performance Considerations
312
+
313
+ ### Memory Usage
314
+
315
+ ```typescript
316
+ // Be careful with large size limits
317
+ json: {
318
+ sizeLimit: '100mb' // Could cause memory issues
319
+ }
320
+
321
+ // Recommended for most applications
322
+ json: {
323
+ sizeLimit: '10mb' // Reasonable limit
324
+ }
325
+ ```
326
+
327
+ ### Streaming for Large Files
328
+
329
+ For very large files, consider using the file upload plugin instead:
330
+
331
+ ```typescript
332
+ // For large files, use file upload plugin
333
+ plugins: {
334
+ file: {
335
+ maxFileSize: 50 * 1024 * 1024 // 50MB
336
+ }
337
+ }
338
+ ```