vibe-gx 1.0.2 → 1.0.4
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/README.md +109 -1
- package/package.json +1 -1
- package/vibe.d.ts +88 -8
package/README.md
CHANGED
|
@@ -120,9 +120,40 @@ app.get("/users", async (req, res) => {
|
|
|
120
120
|
});
|
|
121
121
|
```
|
|
122
122
|
|
|
123
|
-
###
|
|
123
|
+
### File Uploads
|
|
124
|
+
|
|
125
|
+
Vibe supports multipart file uploads with built-in validation.
|
|
126
|
+
|
|
127
|
+
#### Basic File Upload
|
|
128
|
+
|
|
129
|
+
```javascript
|
|
130
|
+
app.post("/upload", { media: { dest: "uploads" } }, (req, res) => {
|
|
131
|
+
return { files: req.files, body: req.body };
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
#### Media Options
|
|
124
136
|
|
|
125
137
|
```javascript
|
|
138
|
+
app.post(
|
|
139
|
+
"/upload",
|
|
140
|
+
{
|
|
141
|
+
media: {
|
|
142
|
+
dest: "uploads", // Folder to save files
|
|
143
|
+
public: true, // Save inside public folder (default: true)
|
|
144
|
+
maxSize: 5 * 1024 * 1024, // Max file size: 5MB
|
|
145
|
+
allowedTypes: ["image/jpeg", "image/png", "application/pdf"],
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
handler,
|
|
149
|
+
);
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
#### Streaming Uploads (Large Files)
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
import fs from "fs";
|
|
156
|
+
|
|
126
157
|
app.post("/upload", { media: { streaming: true } }, (req, res) => {
|
|
127
158
|
req.on("file", (name, stream, info) => {
|
|
128
159
|
stream.pipe(fs.createWriteStream(`/uploads/${info.filename}`));
|
|
@@ -131,8 +162,85 @@ app.post("/upload", { media: { streaming: true } }, (req, res) => {
|
|
|
131
162
|
});
|
|
132
163
|
```
|
|
133
164
|
|
|
165
|
+
#### Uploaded File Object
|
|
166
|
+
|
|
167
|
+
```javascript
|
|
168
|
+
// req.files contains:
|
|
169
|
+
[
|
|
170
|
+
{
|
|
171
|
+
filename: "image-a7x92b.png", // Saved filename
|
|
172
|
+
originalName: "photo.png", // Original filename
|
|
173
|
+
type: "image/png", // MIME type
|
|
174
|
+
filePath: "/uploads/image.png", // Full path
|
|
175
|
+
size: 102400, // Size in bytes
|
|
176
|
+
},
|
|
177
|
+
];
|
|
178
|
+
```
|
|
179
|
+
|
|
134
180
|
---
|
|
135
181
|
|
|
182
|
+
### Interceptors (Middleware)
|
|
183
|
+
|
|
184
|
+
Interceptors run before your handler. Return `false` to stop execution.
|
|
185
|
+
|
|
186
|
+
#### Single Interceptor
|
|
187
|
+
|
|
188
|
+
```javascript
|
|
189
|
+
const authCheck = (req, res) => {
|
|
190
|
+
if (!req.headers.authorization) {
|
|
191
|
+
res.unauthorized("Token required");
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
req.user = { id: 1 };
|
|
195
|
+
return true;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
app.get("/protected", { intercept: authCheck }, (req) => {
|
|
199
|
+
return { user: req.user };
|
|
200
|
+
});
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
#### Multiple Interceptors
|
|
204
|
+
|
|
205
|
+
```javascript
|
|
206
|
+
app.get(
|
|
207
|
+
"/admin",
|
|
208
|
+
{
|
|
209
|
+
intercept: [authCheck, adminCheck, rateLimiter],
|
|
210
|
+
},
|
|
211
|
+
handler,
|
|
212
|
+
);
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
#### Global Interceptors
|
|
216
|
+
|
|
217
|
+
```javascript
|
|
218
|
+
// Applies to ALL routes
|
|
219
|
+
app.plugin((req, res) => {
|
|
220
|
+
console.log(`${req.method} ${req.url}`);
|
|
221
|
+
});
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
### Route Options
|
|
227
|
+
|
|
228
|
+
```javascript
|
|
229
|
+
app.post(
|
|
230
|
+
"/path",
|
|
231
|
+
{
|
|
232
|
+
intercept: authMiddleware, // Middleware function(s)
|
|
233
|
+
media: {
|
|
234
|
+
// File upload config
|
|
235
|
+
dest: "uploads",
|
|
236
|
+
maxSize: 10 * 1024 * 1024,
|
|
237
|
+
allowedTypes: ["image/*"],
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
handler,
|
|
241
|
+
);
|
|
242
|
+
```
|
|
243
|
+
|
|
136
244
|
## 🛠️ API Reference
|
|
137
245
|
|
|
138
246
|
### Application
|
package/package.json
CHANGED
package/vibe.d.ts
CHANGED
|
@@ -26,25 +26,67 @@ export interface UploadedFile {
|
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Configuration for file uploads on a specific route.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* {
|
|
32
|
+
* dest: "uploads",
|
|
33
|
+
* maxSize: 5 * 1024 * 1024, // 5MB
|
|
34
|
+
* allowedTypes: ["image/jpeg", "image/png"],
|
|
35
|
+
* public: true
|
|
36
|
+
* }
|
|
29
37
|
*/
|
|
30
38
|
export interface MediaOptions {
|
|
31
39
|
/** Save file inside the configured public folder. Default: true */
|
|
32
40
|
public?: boolean;
|
|
33
41
|
/** Subfolder destination for uploads (e.g., "uploads/avatars") */
|
|
34
42
|
dest?: string;
|
|
35
|
-
/** Maximum allowed file size in bytes. Default: 10 MB */
|
|
43
|
+
/** Maximum allowed file size in bytes. Default: 10 MB (10485760) */
|
|
36
44
|
maxSize?: number;
|
|
37
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* Allowed MIME types. Supports wildcards like "image/*"
|
|
47
|
+
* @example ["image/jpeg", "image/png", "application/pdf"]
|
|
48
|
+
*/
|
|
38
49
|
allowedTypes?: string[];
|
|
50
|
+
/** Enable streaming mode for large files. Use req.on('file', ...) */
|
|
51
|
+
streaming?: boolean;
|
|
39
52
|
}
|
|
40
53
|
|
|
41
54
|
/**
|
|
42
55
|
* Options for registering a route.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* // With interceptor only
|
|
59
|
+
* { intercept: authMiddleware }
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* // With file upload
|
|
63
|
+
* {
|
|
64
|
+
* intercept: authMiddleware,
|
|
65
|
+
* media: {
|
|
66
|
+
* dest: "uploads",
|
|
67
|
+
* maxSize: 10 * 1024 * 1024,
|
|
68
|
+
* allowedTypes: ["image/*"]
|
|
69
|
+
* }
|
|
70
|
+
* }
|
|
43
71
|
*/
|
|
44
72
|
export interface RouteOptions {
|
|
45
|
-
/**
|
|
73
|
+
/**
|
|
74
|
+
* Middleware function(s) to run before the handler.
|
|
75
|
+
* Return false to stop execution.
|
|
76
|
+
* @example
|
|
77
|
+
* intercept: (req, res) => {
|
|
78
|
+
* if (!req.headers.authorization) {
|
|
79
|
+
* res.unauthorized();
|
|
80
|
+
* return false;
|
|
81
|
+
* }
|
|
82
|
+
* return true;
|
|
83
|
+
* }
|
|
84
|
+
*/
|
|
46
85
|
intercept?: Interceptor | Interceptor[];
|
|
47
|
-
/**
|
|
86
|
+
/**
|
|
87
|
+
* Configuration for file uploads (multipart/form-data).
|
|
88
|
+
* Files will be available in req.files array.
|
|
89
|
+
*/
|
|
48
90
|
media?: MediaOptions;
|
|
49
91
|
}
|
|
50
92
|
|
|
@@ -89,7 +131,13 @@ export interface VibeResponse extends ServerResponse {
|
|
|
89
131
|
json: (data: any) => void;
|
|
90
132
|
send: (data: string | number | boolean | object) => void;
|
|
91
133
|
status: (code: number) => VibeResponse;
|
|
134
|
+
/** Send a file from the public folder */
|
|
92
135
|
sendFile: (filePath: string) => void;
|
|
136
|
+
/** Send any file by absolute path */
|
|
137
|
+
sendAbsoluteFile: (
|
|
138
|
+
absolutePath: string,
|
|
139
|
+
opts?: { download?: boolean; filename?: string },
|
|
140
|
+
) => void;
|
|
93
141
|
sendHtml: (filename: string) => void;
|
|
94
142
|
redirect: (url: string, code?: number) => void;
|
|
95
143
|
|
|
@@ -167,13 +215,45 @@ export const color: Record<ColorName, (text: string) => string>;
|
|
|
167
215
|
|
|
168
216
|
/**
|
|
169
217
|
* Route registration function.
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* // Simple handler
|
|
221
|
+
* app.get("/path", (req, res) => { ... });
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* // Static response
|
|
225
|
+
* app.get("/", "Hello World");
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* // With options (interceptor + file upload)
|
|
229
|
+
* app.post("/upload", {
|
|
230
|
+
* intercept: authMiddleware,
|
|
231
|
+
* media: {
|
|
232
|
+
* dest: "uploads",
|
|
233
|
+
* maxSize: 10 * 1024 * 1024,
|
|
234
|
+
* allowedTypes: ["image/*"]
|
|
235
|
+
* }
|
|
236
|
+
* }, handler);
|
|
173
237
|
*/
|
|
174
238
|
export interface RouteRegistrar {
|
|
239
|
+
/**
|
|
240
|
+
* Register a route with a handler or static response.
|
|
241
|
+
* @param path - Route path (e.g., "/users/:id")
|
|
242
|
+
* @param handler - Handler function, string, number, or object
|
|
243
|
+
*/
|
|
175
244
|
(path: string, handler: Handler | string | number | object): void;
|
|
176
|
-
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Register a route with options and handler.
|
|
248
|
+
* @param path - Route path (e.g., "/upload")
|
|
249
|
+
* @param options - Route options (intercept, media)
|
|
250
|
+
* @param handler - Handler function
|
|
251
|
+
*/
|
|
252
|
+
(
|
|
253
|
+
path: string,
|
|
254
|
+
options: RouteOptions,
|
|
255
|
+
handler: Handler | string | number | object,
|
|
256
|
+
): void;
|
|
177
257
|
}
|
|
178
258
|
|
|
179
259
|
/** Sub-router or prefixed router instance */
|