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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibe-gx",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "A lightweight, regex-based Node.js web framework built for speed and simplicity.",
5
5
  "type": "module",
6
6
  "main": "vibe.js",
@@ -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
- if (!media.allowedTypes.includes(mimeType)) {
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
- if (fileError) {
176
- reject(fileError);
177
- } else {
178
- resolve();
179
- }
209
+ busboyFinished = true;
210
+ checkComplete();
180
211
  });
181
212
 
182
213
  req.pipe(bb);