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.
- package/lib/cli.d.ts +6 -0
- package/lib/cli.js +929 -0
- package/lib/cli.js.map +1 -0
- package/lib/index.cjs +3384 -0
- package/lib/index.cjs.map +1 -0
- package/lib/index.d.cts +1492 -0
- package/lib/index.d.ts +1492 -0
- package/lib/index.js +3327 -0
- package/lib/index.js.map +1 -0
- package/package.json +1 -1
- package/.husky/pre-commit +0 -19
- package/.nvmrc +0 -1
- package/docs/README.md +0 -135
- package/docs/blog/authors.yml +0 -6
- package/docs/blog/tags.yml +0 -4
- package/docs/cli.md +0 -109
- package/docs/docs/core-concepts/controllers.md +0 -393
- package/docs/docs/core-concepts/middleware.md +0 -302
- package/docs/docs/core-concepts/request-response.md +0 -486
- package/docs/docs/core-concepts/routing.md +0 -388
- package/docs/docs/core-concepts/server.md +0 -332
- package/docs/docs/cron/overview.md +0 -70
- package/docs/docs/examples/rest-api.md +0 -595
- package/docs/docs/getting-started/configuration.md +0 -168
- package/docs/docs/getting-started/installation.md +0 -125
- package/docs/docs/getting-started/quick-start.md +0 -273
- package/docs/docs/intro.md +0 -46
- package/docs/docs/plugins/cookie.md +0 -424
- package/docs/docs/plugins/cors.md +0 -295
- package/docs/docs/plugins/file.md +0 -382
- package/docs/docs/plugins/helmet.md +0 -388
- package/docs/docs/plugins/json.md +0 -338
- package/docs/docs/plugins/log.md +0 -592
- package/docs/docs/plugins/overview.md +0 -390
- package/docs/docs/plugins/rate-limiter.md +0 -347
- package/docs/docs/plugins/static.md +0 -352
- package/docs/docs/plugins/swagger.md +0 -411
- package/docs/docs/plugins/urlencoded.md +0 -76
- package/docs/docs/testing/examples.md +0 -384
- package/docs/docs/testing/mock-server.md +0 -311
- package/docs/docs/testing/overview.md +0 -76
- package/docs/docusaurus.config.ts +0 -144
- package/docs/intro.md +0 -78
- package/docs/package.json +0 -46
- package/docs/sidebars.ts +0 -72
- package/docs/static/.nojekyll +0 -0
- package/docs/static/img/docusaurus-social-card.jpg +0 -0
- package/docs/static/img/docusaurus.png +0 -0
- package/docs/static/img/favicon.ico +0 -0
- package/docs/static/img/logo.svg +0 -1
- package/docs/static/img/undraw_docusaurus_mountain.svg +0 -37
- package/docs/static/img/undraw_docusaurus_react.svg +0 -170
- package/docs/static/img/undraw_docusaurus_tree.svg +0 -40
- package/docs/tsconfig.json +0 -8
- package/speed_test.sh +0 -3
- package/test/benchmark/index.ts +0 -17
- package/test/cli/cli.ts +0 -7
- package/test/commands/test.ts +0 -42
- package/test/controllers/file_upload.ts +0 -29
- package/test/controllers/urlencoded.ts +0 -13
- package/test/controllers/users.ts +0 -111
- package/test/cron/index.ts +0 -6
- package/test/cron/test_cron.ts +0 -8
- package/test/cron/test_cron_imported.ts +0 -8
- package/test/native_env.ts +0 -16
- package/test/resources/test.txt +0 -1
- package/test/server/index.ts +0 -3
- package/test/server/instance.ts +0 -63
- package/test/suite/upload.test.ts +0 -23
- package/test/suite/urlencoded.test.ts +0 -23
- package/test/suite/users.test.ts +0 -76
- package/todo.md +0 -9
- package/tsconfig.json +0 -24
- package/vitest.config.ts +0 -17
@@ -1,382 +0,0 @@
|
|
1
|
-
---
|
2
|
-
sidebar_position: 10
|
3
|
-
---
|
4
|
-
|
5
|
-
# File Plugin
|
6
|
-
|
7
|
-
The File plugin handles multipart/form-data file uploads in your Balda.js application. It automatically parses uploaded files, validates them against size limits, and provides convenient access to file data through `req.files` and `req.file`.
|
8
|
-
|
9
|
-
## Features
|
10
|
-
|
11
|
-
- **Multipart Form Data**: Handles file uploads from HTML forms
|
12
|
-
- **Size Validation**: Configurable file size limits
|
13
|
-
- **Automatic Cleanup**: Temporary files are cleaned up automatically
|
14
|
-
- **Multiple Files**: Support for single and multiple file uploads
|
15
|
-
- **File Metadata**: Access to file name, size, MIME type, and temporary path
|
16
|
-
- **Error Handling**: Graceful handling of file upload errors
|
17
|
-
|
18
|
-
## Basic Configuration
|
19
|
-
|
20
|
-
### Simple Setup
|
21
|
-
|
22
|
-
```typescript
|
23
|
-
import { Server } from 'balda-js';
|
24
|
-
|
25
|
-
const server = new Server({
|
26
|
-
port: 3000,
|
27
|
-
plugins: {
|
28
|
-
file: {
|
29
|
-
maxFileSize: 5 * 1024 * 1024 // 5MB
|
30
|
-
}
|
31
|
-
}
|
32
|
-
});
|
33
|
-
```
|
34
|
-
|
35
|
-
### Advanced Configuration
|
36
|
-
|
37
|
-
```typescript
|
38
|
-
const server = new Server({
|
39
|
-
port: 3000,
|
40
|
-
plugins: {
|
41
|
-
file: {
|
42
|
-
maxFileSize: 10 * 1024 * 1024, // 10MB
|
43
|
-
allowedMimeTypes: ['image/jpeg', 'image/png', 'application/pdf']
|
44
|
-
}
|
45
|
-
}
|
46
|
-
});
|
47
|
-
```
|
48
|
-
|
49
|
-
## Configuration Options
|
50
|
-
|
51
|
-
### Basic Options
|
52
|
-
|
53
|
-
```typescript
|
54
|
-
file: {
|
55
|
-
maxFileSize: 5 * 1024 * 1024, // Maximum file size in bytes (default: 5MB)
|
56
|
-
}
|
57
|
-
```
|
58
|
-
|
59
|
-
### Advanced Options
|
60
|
-
|
61
|
-
```typescript
|
62
|
-
file: {
|
63
|
-
maxFileSize: 10 * 1024 * 1024, // 10MB
|
64
|
-
allowedMimeTypes: ['image/jpeg', 'image/png', 'application/pdf'],
|
65
|
-
maxFiles: 5, // Maximum number of files per request
|
66
|
-
preserveExtension: true // Preserve original file extensions
|
67
|
-
}
|
68
|
-
```
|
69
|
-
|
70
|
-
## Usage Examples
|
71
|
-
|
72
|
-
### Basic File Upload
|
73
|
-
|
74
|
-
```typescript
|
75
|
-
@controller('/upload')
|
76
|
-
export class UploadController {
|
77
|
-
@post('/single')
|
78
|
-
async uploadSingleFile(req: Request, res: Response) {
|
79
|
-
if (!req.files || req.files.length === 0) {
|
80
|
-
return res.badRequest({ error: 'No file uploaded' });
|
81
|
-
}
|
82
|
-
|
83
|
-
const file = req.files[0];
|
84
|
-
|
85
|
-
// Access file properties
|
86
|
-
console.log('File name:', file.originalName);
|
87
|
-
console.log('File size:', file.size);
|
88
|
-
console.log('MIME type:', file.mimeType);
|
89
|
-
console.log('Temporary path:', file.tmpPath);
|
90
|
-
|
91
|
-
// Process the file (e.g., move to permanent location)
|
92
|
-
const permanentPath = await moveFileToPermanentLocation(file.tmpPath, file.originalName);
|
93
|
-
|
94
|
-
res.json({
|
95
|
-
message: 'File uploaded successfully',
|
96
|
-
file: {
|
97
|
-
name: file.originalName,
|
98
|
-
size: file.size,
|
99
|
-
path: permanentPath
|
100
|
-
}
|
101
|
-
});
|
102
|
-
}
|
103
|
-
}
|
104
|
-
```
|
105
|
-
|
106
|
-
### Multiple File Upload
|
107
|
-
|
108
|
-
```typescript
|
109
|
-
@controller('/upload')
|
110
|
-
export class UploadController {
|
111
|
-
@post('/multiple')
|
112
|
-
async uploadMultipleFiles(req: Request, res: Response) {
|
113
|
-
if (!req.files || req.files.length === 0) {
|
114
|
-
return res.badRequest({ error: 'No files uploaded' });
|
115
|
-
}
|
116
|
-
|
117
|
-
const uploadedFiles = [];
|
118
|
-
|
119
|
-
for (const file of req.files) {
|
120
|
-
// Process each file
|
121
|
-
const permanentPath = await moveFileToPermanentLocation(file.tmpPath, file.originalName);
|
122
|
-
|
123
|
-
uploadedFiles.push({
|
124
|
-
name: file.originalName,
|
125
|
-
size: file.size,
|
126
|
-
mimeType: file.mimeType,
|
127
|
-
path: permanentPath
|
128
|
-
});
|
129
|
-
}
|
130
|
-
|
131
|
-
res.json({
|
132
|
-
message: `${uploadedFiles.length} files uploaded successfully`,
|
133
|
-
files: uploadedFiles
|
134
|
-
});
|
135
|
-
}
|
136
|
-
}
|
137
|
-
```
|
138
|
-
|
139
|
-
### File Upload with Form Data
|
140
|
-
|
141
|
-
```typescript
|
142
|
-
@controller('/upload')
|
143
|
-
export class UploadController {
|
144
|
-
@post('/with-data')
|
145
|
-
async uploadWithData(req: Request, res: Response) {
|
146
|
-
// Access uploaded files
|
147
|
-
const files = req.files || [];
|
148
|
-
|
149
|
-
// Access form data
|
150
|
-
const title = req.body.title;
|
151
|
-
const description = req.body.description;
|
152
|
-
const category = req.body.category;
|
153
|
-
|
154
|
-
if (files.length === 0) {
|
155
|
-
return res.badRequest({ error: 'No file uploaded' });
|
156
|
-
}
|
157
|
-
|
158
|
-
const file = files[0];
|
159
|
-
|
160
|
-
// Save file and metadata to database
|
161
|
-
const savedFile = await saveFileToDatabase({
|
162
|
-
title,
|
163
|
-
description,
|
164
|
-
category,
|
165
|
-
fileName: file.originalName,
|
166
|
-
fileSize: file.size,
|
167
|
-
mimeType: file.mimeType,
|
168
|
-
filePath: await moveFileToPermanentLocation(file.tmpPath, file.originalName)
|
169
|
-
});
|
170
|
-
|
171
|
-
res.json({
|
172
|
-
message: 'File uploaded with metadata',
|
173
|
-
file: savedFile
|
174
|
-
});
|
175
|
-
}
|
176
|
-
}
|
177
|
-
```
|
178
|
-
|
179
|
-
### Image Upload with Validation
|
180
|
-
|
181
|
-
```typescript
|
182
|
-
@controller('/upload')
|
183
|
-
export class ImageController {
|
184
|
-
@post('/image')
|
185
|
-
async uploadImage(req: Request, res: Response) {
|
186
|
-
if (!req.files || req.files.length === 0) {
|
187
|
-
return res.badRequest({ error: 'No image uploaded' });
|
188
|
-
}
|
189
|
-
|
190
|
-
const file = req.files[0];
|
191
|
-
|
192
|
-
// Validate image type
|
193
|
-
const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
|
194
|
-
if (!allowedTypes.includes(file.mimeType)) {
|
195
|
-
return res.badRequest({
|
196
|
-
error: 'Invalid file type. Only JPEG, PNG, GIF, and WebP are allowed.'
|
197
|
-
});
|
198
|
-
}
|
199
|
-
|
200
|
-
// Validate file size (max 2MB for images)
|
201
|
-
const maxSize = 2 * 1024 * 1024; // 2MB
|
202
|
-
if (file.size > maxSize) {
|
203
|
-
return res.badRequest({
|
204
|
-
error: 'File too large. Maximum size is 2MB.'
|
205
|
-
});
|
206
|
-
}
|
207
|
-
|
208
|
-
// Process image (e.g., resize, compress)
|
209
|
-
const processedPath = await processImage(file.tmpPath);
|
210
|
-
|
211
|
-
res.json({
|
212
|
-
message: 'Image uploaded successfully',
|
213
|
-
image: {
|
214
|
-
name: file.originalName,
|
215
|
-
size: file.size,
|
216
|
-
type: file.mimeType,
|
217
|
-
path: processedPath
|
218
|
-
}
|
219
|
-
});
|
220
|
-
}
|
221
|
-
}
|
222
|
-
```
|
223
|
-
|
224
|
-
## File Object Properties
|
225
|
-
|
226
|
-
### File Structure
|
227
|
-
|
228
|
-
```typescript
|
229
|
-
interface FormFile {
|
230
|
-
formName: string; // The name of the form field
|
231
|
-
mimeType: string; // MIME type (e.g., "image/png")
|
232
|
-
size: number; // File size in bytes
|
233
|
-
tmpPath: string; // Temporary file path
|
234
|
-
originalName: string; // Original filename with extension
|
235
|
-
}
|
236
|
-
```
|
237
|
-
|
238
|
-
### Accessing File Properties
|
239
|
-
|
240
|
-
```typescript
|
241
|
-
@post('/file-info')
|
242
|
-
async getFileInfo(req: Request, res: Response) {
|
243
|
-
if (!req.files || req.files.length === 0) {
|
244
|
-
return res.badRequest({ error: 'No file uploaded' });
|
245
|
-
}
|
246
|
-
|
247
|
-
const file = req.files[0];
|
248
|
-
|
249
|
-
res.json({
|
250
|
-
formField: file.formName,
|
251
|
-
originalName: file.originalName,
|
252
|
-
mimeType: file.mimeType,
|
253
|
-
size: file.size,
|
254
|
-
sizeInMB: (file.size / (1024 * 1024)).toFixed(2),
|
255
|
-
temporaryPath: file.tmpPath
|
256
|
-
});
|
257
|
-
}
|
258
|
-
```
|
259
|
-
|
260
|
-
## Error Handling
|
261
|
-
|
262
|
-
### File Too Large
|
263
|
-
|
264
|
-
```typescript
|
265
|
-
// When a file exceeds maxFileSize
|
266
|
-
// Response: 400 Bad Request
|
267
|
-
{
|
268
|
-
"error": "File too large",
|
269
|
-
"message": "File 'large-file.zip' (15MB) exceeds the maximum allowed size of 5MB"
|
270
|
-
}
|
271
|
-
```
|
272
|
-
|
273
|
-
### No Files Uploaded
|
274
|
-
|
275
|
-
```typescript
|
276
|
-
@post('/upload')
|
277
|
-
async uploadFile(req: Request, res: Response) {
|
278
|
-
if (!req.files || req.files.length === 0) {
|
279
|
-
return res.badRequest({
|
280
|
-
error: 'No file uploaded',
|
281
|
-
message: 'Please select a file to upload'
|
282
|
-
});
|
283
|
-
}
|
284
|
-
|
285
|
-
// Process file...
|
286
|
-
}
|
287
|
-
```
|
288
|
-
|
289
|
-
### Invalid File Type
|
290
|
-
|
291
|
-
```typescript
|
292
|
-
@post('/upload')
|
293
|
-
async uploadFile(req: Request, res: Response) {
|
294
|
-
if (!req.files || req.files.length === 0) {
|
295
|
-
return res.badRequest({ error: 'No file uploaded' });
|
296
|
-
}
|
297
|
-
|
298
|
-
const file = req.files[0];
|
299
|
-
const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf'];
|
300
|
-
|
301
|
-
if (!allowedTypes.includes(file.mimeType)) {
|
302
|
-
return res.badRequest({
|
303
|
-
error: 'Invalid file type',
|
304
|
-
message: `File type '${file.mimeType}' is not allowed. Allowed types: ${allowedTypes.join(', ')}`
|
305
|
-
});
|
306
|
-
}
|
307
|
-
|
308
|
-
// Process file...
|
309
|
-
}
|
310
|
-
```
|
311
|
-
|
312
|
-
## File Processing Examples
|
313
|
-
|
314
|
-
### Moving Files to Permanent Location
|
315
|
-
|
316
|
-
```typescript
|
317
|
-
@post('/upload')
|
318
|
-
async uploadFile(req: Request, res: Response) {
|
319
|
-
if (!req.files || req.files.length === 0) {
|
320
|
-
return res.badRequest({ error: 'No file uploaded' });
|
321
|
-
}
|
322
|
-
|
323
|
-
const file = req.files[0];
|
324
|
-
const permanentPath = await moveFileToPermanentLocation(file.tmpPath, file.originalName);
|
325
|
-
|
326
|
-
res.json({
|
327
|
-
message: 'File uploaded successfully',
|
328
|
-
path: permanentPath
|
329
|
-
});
|
330
|
-
}
|
331
|
-
|
332
|
-
@post('/image')
|
333
|
-
async uploadImage(req: Request, res: Response) {
|
334
|
-
if (!req.files || req.files.length === 0) {
|
335
|
-
return res.badRequest({ error: 'No image uploaded' });
|
336
|
-
}
|
337
|
-
|
338
|
-
const file = req.files[0];
|
339
|
-
const processedPath = await processImage(file.tmpPath);
|
340
|
-
|
341
|
-
res.json({
|
342
|
-
message: 'Image processed and uploaded',
|
343
|
-
path: processedPath
|
344
|
-
});
|
345
|
-
}
|
346
|
-
```
|
347
|
-
|
348
|
-
## HTML Form Examples
|
349
|
-
|
350
|
-
### Single File Upload
|
351
|
-
|
352
|
-
```html
|
353
|
-
<form action="/upload/single" method="post" enctype="multipart/form-data">
|
354
|
-
<input type="file" name="file" required>
|
355
|
-
<button type="submit">Upload File</button>
|
356
|
-
</form>
|
357
|
-
```
|
358
|
-
|
359
|
-
### Multiple File Upload
|
360
|
-
|
361
|
-
```html
|
362
|
-
<form action="/upload/multiple" method="post" enctype="multipart/form-data">
|
363
|
-
<input type="file" name="files" multiple required>
|
364
|
-
<button type="submit">Upload Files</button>
|
365
|
-
</form>
|
366
|
-
```
|
367
|
-
|
368
|
-
### File Upload with Form Data
|
369
|
-
|
370
|
-
```html
|
371
|
-
<form action="/upload/with-data" method="post" enctype="multipart/form-data">
|
372
|
-
<input type="text" name="title" placeholder="File title" required>
|
373
|
-
<textarea name="description" placeholder="File description"></textarea>
|
374
|
-
<select name="category">
|
375
|
-
<option value="document">Document</option>
|
376
|
-
<option value="image">Image</option>
|
377
|
-
<option value="video">Video</option>
|
378
|
-
</select>
|
379
|
-
<input type="file" name="file" required>
|
380
|
-
<button type="submit">Upload</button>
|
381
|
-
</form>
|
382
|
-
```
|