vibe-gx 1.0.4 → 1.0.5
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/package.json +1 -1
- package/utils/core/parser.js +39 -8
package/package.json
CHANGED
package/utils/core/parser.js
CHANGED
|
@@ -54,6 +54,19 @@ function parseMultipart(req, res, media, options, resolve, reject) {
|
|
|
54
54
|
let bb;
|
|
55
55
|
let fileError = null;
|
|
56
56
|
const streaming = media.streaming === true;
|
|
57
|
+
let pendingWrites = 0;
|
|
58
|
+
let busboyFinished = false;
|
|
59
|
+
|
|
60
|
+
// Helper to check if we're done
|
|
61
|
+
const checkComplete = () => {
|
|
62
|
+
if (busboyFinished && pendingWrites === 0) {
|
|
63
|
+
if (fileError) {
|
|
64
|
+
reject(fileError);
|
|
65
|
+
} else {
|
|
66
|
+
resolve();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
57
70
|
|
|
58
71
|
try {
|
|
59
72
|
bb = busboy({
|
|
@@ -75,9 +88,15 @@ function parseMultipart(req, res, media, options, resolve, reject) {
|
|
|
75
88
|
const { filename, mimeType } = info;
|
|
76
89
|
if (!filename) return file.resume();
|
|
77
90
|
|
|
78
|
-
// File type validation
|
|
91
|
+
// File type validation - support wildcards like "image/*"
|
|
79
92
|
if (media.allowedTypes && Array.isArray(media.allowedTypes)) {
|
|
80
|
-
|
|
93
|
+
const isAllowed = media.allowedTypes.some((allowed) => {
|
|
94
|
+
if (allowed.endsWith("/*")) {
|
|
95
|
+
return mimeType.startsWith(allowed.slice(0, -1));
|
|
96
|
+
}
|
|
97
|
+
return allowed === mimeType;
|
|
98
|
+
});
|
|
99
|
+
if (!isAllowed) {
|
|
81
100
|
fileError = new Error(
|
|
82
101
|
`File type '${mimeType}' not allowed. Allowed: ${media.allowedTypes.join(", ")}`,
|
|
83
102
|
);
|
|
@@ -92,6 +111,8 @@ function parseMultipart(req, res, media, options, resolve, reject) {
|
|
|
92
111
|
}
|
|
93
112
|
|
|
94
113
|
// BUFFERING MODE: Write to disk
|
|
114
|
+
pendingWrites++;
|
|
115
|
+
|
|
95
116
|
const parent = media.public ? options.publicFolder || "" : "";
|
|
96
117
|
const dest = path.resolve(
|
|
97
118
|
path.join(parent, media.dest || (media.public ? "uploads" : "private")),
|
|
@@ -103,6 +124,8 @@ function parseMultipart(req, res, media, options, resolve, reject) {
|
|
|
103
124
|
!dest.startsWith(path.resolve(options.publicFolder || ""))
|
|
104
125
|
) {
|
|
105
126
|
console.warn("Attempted upload outside public folder, skipping");
|
|
127
|
+
pendingWrites--;
|
|
128
|
+
checkComplete();
|
|
106
129
|
return file.resume();
|
|
107
130
|
}
|
|
108
131
|
|
|
@@ -110,6 +133,8 @@ function parseMultipart(req, res, media, options, resolve, reject) {
|
|
|
110
133
|
if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
|
|
111
134
|
} catch (err) {
|
|
112
135
|
console.error("Failed to create upload folder:", err);
|
|
136
|
+
pendingWrites--;
|
|
137
|
+
checkComplete();
|
|
113
138
|
return file.resume();
|
|
114
139
|
}
|
|
115
140
|
|
|
@@ -137,17 +162,24 @@ function parseMultipart(req, res, media, options, resolve, reject) {
|
|
|
137
162
|
file.unpipe(writeStream);
|
|
138
163
|
writeStream.end();
|
|
139
164
|
// Clean up partial file
|
|
140
|
-
fs.unlink(filePath, () => {
|
|
165
|
+
fs.unlink(filePath, () => {
|
|
166
|
+
pendingWrites--;
|
|
167
|
+
checkComplete();
|
|
168
|
+
});
|
|
141
169
|
});
|
|
142
170
|
|
|
143
171
|
file.on("error", (err) => {
|
|
144
172
|
console.error("File stream error:", err);
|
|
145
173
|
writeStream.end();
|
|
174
|
+
pendingWrites--;
|
|
175
|
+
checkComplete();
|
|
146
176
|
});
|
|
147
177
|
|
|
148
178
|
writeStream.on("error", (err) => {
|
|
149
179
|
console.error("Write stream error:", err);
|
|
150
180
|
file.resume();
|
|
181
|
+
pendingWrites--;
|
|
182
|
+
checkComplete();
|
|
151
183
|
});
|
|
152
184
|
|
|
153
185
|
writeStream.on("finish", () => {
|
|
@@ -160,6 +192,8 @@ function parseMultipart(req, res, media, options, resolve, reject) {
|
|
|
160
192
|
size,
|
|
161
193
|
});
|
|
162
194
|
}
|
|
195
|
+
pendingWrites--;
|
|
196
|
+
checkComplete();
|
|
163
197
|
});
|
|
164
198
|
|
|
165
199
|
file.pipe(writeStream);
|
|
@@ -172,11 +206,8 @@ function parseMultipart(req, res, media, options, resolve, reject) {
|
|
|
172
206
|
});
|
|
173
207
|
|
|
174
208
|
bb.on("finish", () => {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
} else {
|
|
178
|
-
resolve();
|
|
179
|
-
}
|
|
209
|
+
busboyFinished = true;
|
|
210
|
+
checkComplete();
|
|
180
211
|
});
|
|
181
212
|
|
|
182
213
|
req.pipe(bb);
|