@bepalo/router 1.0.3

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 (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +557 -0
  3. package/dist/cjs/helpers.d.ts +290 -0
  4. package/dist/cjs/helpers.d.ts.map +1 -0
  5. package/dist/cjs/helpers.js +691 -0
  6. package/dist/cjs/helpers.js.map +1 -0
  7. package/dist/cjs/index.d.ts +5 -0
  8. package/dist/cjs/index.d.ts.map +1 -0
  9. package/dist/cjs/index.js +21 -0
  10. package/dist/cjs/index.js.map +1 -0
  11. package/dist/cjs/list.d.ts +166 -0
  12. package/dist/cjs/list.d.ts.map +1 -0
  13. package/dist/cjs/list.js +483 -0
  14. package/dist/cjs/list.js.map +1 -0
  15. package/dist/cjs/middlewares.d.ts +251 -0
  16. package/dist/cjs/middlewares.d.ts.map +1 -0
  17. package/dist/cjs/middlewares.js +359 -0
  18. package/dist/cjs/middlewares.js.map +1 -0
  19. package/dist/cjs/router.d.ts +333 -0
  20. package/dist/cjs/router.d.ts.map +1 -0
  21. package/dist/cjs/router.js +659 -0
  22. package/dist/cjs/router.js.map +1 -0
  23. package/dist/cjs/tree.d.ts +18 -0
  24. package/dist/cjs/tree.d.ts.map +1 -0
  25. package/dist/cjs/tree.js +162 -0
  26. package/dist/cjs/tree.js.map +1 -0
  27. package/dist/cjs/types.d.ts +127 -0
  28. package/dist/cjs/types.d.ts.map +1 -0
  29. package/dist/cjs/types.js +3 -0
  30. package/dist/cjs/types.js.map +1 -0
  31. package/dist/cjs/upload-stream.d.ts +105 -0
  32. package/dist/cjs/upload-stream.d.ts.map +1 -0
  33. package/dist/cjs/upload-stream.js +417 -0
  34. package/dist/cjs/upload-stream.js.map +1 -0
  35. package/dist/helpers.d.ts +290 -0
  36. package/dist/helpers.d.ts.map +1 -0
  37. package/dist/helpers.js +691 -0
  38. package/dist/helpers.js.map +1 -0
  39. package/dist/index.d.ts +5 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +21 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/list.d.ts +166 -0
  44. package/dist/list.d.ts.map +1 -0
  45. package/dist/list.js +483 -0
  46. package/dist/list.js.map +1 -0
  47. package/dist/middlewares.d.ts +251 -0
  48. package/dist/middlewares.d.ts.map +1 -0
  49. package/dist/middlewares.js +359 -0
  50. package/dist/middlewares.js.map +1 -0
  51. package/dist/router.d.ts +333 -0
  52. package/dist/router.d.ts.map +1 -0
  53. package/dist/router.js +659 -0
  54. package/dist/router.js.map +1 -0
  55. package/dist/tree.d.ts +18 -0
  56. package/dist/tree.d.ts.map +1 -0
  57. package/dist/tree.js +162 -0
  58. package/dist/tree.js.map +1 -0
  59. package/dist/types.d.ts +127 -0
  60. package/dist/types.d.ts.map +1 -0
  61. package/dist/types.js +3 -0
  62. package/dist/types.js.map +1 -0
  63. package/dist/upload-stream.d.ts +105 -0
  64. package/dist/upload-stream.d.ts.map +1 -0
  65. package/dist/upload-stream.js +417 -0
  66. package/dist/upload-stream.js.map +1 -0
  67. package/package.json +51 -0
@@ -0,0 +1,417 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.parseUploadStreaming = void 0;
13
+ const helpers_js_1 = require("./helpers.js");
14
+ /**
15
+ * Creates a middleware function for streaming multipart/form-data upload parsing.
16
+ * This function processes uploads in chunks as they arrive, allowing for handling
17
+ * of large files without buffering the entire request in memory.
18
+ *
19
+ * @param {StreamingUploadOptions} [options] - Configuration options for upload parsing
20
+ * @returns {Function} A middleware function that adds uploaded files and fields to context
21
+ * @throws {Response} Returns a 415 response if content-type is not multipart/form-data
22
+ * @throws {Response} Returns a 400 response if boundary is missing in Content-Type
23
+ * @throws {Response} Returns a 413 response if request or file exceeds size limits
24
+ * @throws {Response} Returns a 415 response if file type is not allowed
25
+ * @throws {Response} Returns a 400 response if maximum file/field count is exceeded
26
+ *
27
+ * @example
28
+ * const uploadHandler = parseUploadStreaming({
29
+ * maxFileSize: 10 * 1024 * 1024, // 10MB
30
+ * allowedTypes: ['image/jpeg', 'image/png'],
31
+ * onFileStart: async (uploadId, fieldName, fileName, contentType) => {
32
+ * console.log(`Starting upload: ${fileName}`);
33
+ * return { customFilename: `custom_${Date.now()}_${fileName}` };
34
+ * },
35
+ * onFileChunk: async (uploadId, fieldName, fileName, chunk, offset, isLast) => {
36
+ * console.log(`Received chunk for ${fileName}: ${chunk.length} bytes at offset ${offset}`);
37
+ * }
38
+ * });
39
+ *
40
+ * // Use in respondWith:
41
+ * const handler = respondWith({}, uploadHandler, (req, ctx) => {
42
+ * return json({
43
+ * uploadId: ctx.uploadId,
44
+ * files: Array.from(ctx.files.entries()),
45
+ * fields: Array.from(ctx.fields.entries())
46
+ * });
47
+ * });
48
+ */
49
+ const parseUploadStreaming = (options) => {
50
+ const { maxTotalSize = 100 * 1024 * 1024, // 100MB default
51
+ maxFileSize = 20 * 1024 * 1024, // 20MB per file
52
+ maxFiles = 50, maxFields = 1000, allowedTypes, uploadIdGenerator = () => `upload_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, onUploadStart, onUploadComplete, onFileStart, onFileChunk, onFileComplete, onFileError, onField, onError, } = options || {};
53
+ return (req, ctx) => __awaiter(void 0, void 0, void 0, function* () {
54
+ var _a;
55
+ const contentType = req.headers.get("content-type");
56
+ // Check if it's multipart/form-data
57
+ if (!(contentType === null || contentType === void 0 ? void 0 : contentType.startsWith("multipart/form-data"))) {
58
+ return (0, helpers_js_1.status)(415, "Expected multipart/form-data");
59
+ }
60
+ // Get boundary from content-type
61
+ const boundaryMatch = contentType.match(/boundary=(?:"([^"]+)"|([^;]+))/i);
62
+ if (!boundaryMatch) {
63
+ return (0, helpers_js_1.status)(400, "Missing boundary in Content-Type");
64
+ }
65
+ const boundary = boundaryMatch[1] || boundaryMatch[2];
66
+ // Generate upload ID
67
+ const uploadId = yield uploadIdGenerator();
68
+ ctx.uploadId = uploadId;
69
+ ctx.files = new Map();
70
+ ctx.fields = new Map();
71
+ try {
72
+ const reader = (_a = req.body) === null || _a === void 0 ? void 0 : _a.getReader();
73
+ if (!reader) {
74
+ throw new Error("No request body");
75
+ }
76
+ // Initialize tracking
77
+ let buffer = new Uint8Array();
78
+ let totalRead = 0;
79
+ let fileCount = 0;
80
+ let fieldCount = 0;
81
+ let currentPart = null;
82
+ const boundaryBytes = new TextEncoder().encode(`--${boundary}`);
83
+ const boundaryEndBytes = new TextEncoder().encode(`--${boundary}--`);
84
+ const crlfBytes = new TextEncoder().encode("\r\n");
85
+ const headerEndBytes = new TextEncoder().encode("\r\n\r\n");
86
+ // Notify upload start
87
+ if (onUploadStart) {
88
+ const contentLength = req.headers.get("content-length");
89
+ yield onUploadStart(uploadId, contentLength ? parseInt(contentLength) : 0);
90
+ }
91
+ // Process streaming data
92
+ while (true) {
93
+ const { done, value } = yield reader.read();
94
+ if (done)
95
+ break;
96
+ totalRead += value.length;
97
+ if (totalRead > maxTotalSize) {
98
+ yield reader.cancel();
99
+ throw new Error(`Request exceeds maximum size of ${maxTotalSize} bytes`);
100
+ }
101
+ // Add new data to buffer
102
+ const newBuffer = new Uint8Array(buffer.length + value.length);
103
+ newBuffer.set(buffer);
104
+ newBuffer.set(value, buffer.length);
105
+ buffer = newBuffer;
106
+ // Process while we have data
107
+ let processed = false;
108
+ do {
109
+ processed = false;
110
+ if (!currentPart) {
111
+ // Look for boundary to start new part
112
+ const boundaryIndex = findSequence(buffer, boundaryBytes);
113
+ if (boundaryIndex !== -1) {
114
+ // Check if this is the closing boundary
115
+ const isClosingBoundary = buffer.length >= boundaryIndex + boundaryBytes.length + 2 &&
116
+ buffer[boundaryIndex + boundaryBytes.length] === 45 && // '-'
117
+ buffer[boundaryIndex + boundaryBytes.length + 1] === 45; // '-'
118
+ if (isClosingBoundary) {
119
+ // End of multipart data
120
+ buffer = buffer.slice(boundaryIndex + boundaryEndBytes.length);
121
+ break;
122
+ }
123
+ // Remove boundary and look for headers
124
+ buffer = buffer.slice(boundaryIndex + boundaryBytes.length);
125
+ // Look for header end
126
+ const headerEndIndex = findSequence(buffer, headerEndBytes);
127
+ if (headerEndIndex !== -1) {
128
+ const headerBytes = buffer.slice(0, headerEndIndex);
129
+ const headers = parseHeaders(new TextDecoder().decode(headerBytes));
130
+ // Parse content-disposition
131
+ const contentDisposition = headers.get("content-disposition");
132
+ if (contentDisposition) {
133
+ const dispositionParams = parseDisposition(contentDisposition);
134
+ const fieldName = dispositionParams.get("name");
135
+ const fileName = dispositionParams.get("filename");
136
+ const contentType = headers.get("content-type") || "application/octet-stream";
137
+ if (fieldName) {
138
+ currentPart = {
139
+ headers,
140
+ fieldName,
141
+ fileName,
142
+ contentType,
143
+ bytesRead: 0,
144
+ isProcessing: false,
145
+ };
146
+ // Remove headers from buffer
147
+ buffer = buffer.slice(headerEndIndex + headerEndBytes.length);
148
+ // Start processing this part
149
+ processed = true;
150
+ }
151
+ }
152
+ }
153
+ }
154
+ }
155
+ if (currentPart && !currentPart.isProcessing) {
156
+ // Initialize part processing
157
+ currentPart.isProcessing = true;
158
+ if (currentPart.fileName) {
159
+ // This is a file
160
+ fileCount++;
161
+ if (fileCount > maxFiles) {
162
+ throw new Error(`Maximum number of files (${maxFiles}) exceeded`);
163
+ }
164
+ if (allowedTypes &&
165
+ !allowedTypes.includes(currentPart.contentType)) {
166
+ throw new Error(`File type ${currentPart.contentType} not allowed`);
167
+ }
168
+ // Call onFileStart
169
+ if (onFileStart) {
170
+ try {
171
+ const result = yield onFileStart(uploadId, currentPart.fieldName, currentPart.fileName, currentPart.contentType);
172
+ if (result) {
173
+ currentPart.customFilename = result.customFilename;
174
+ currentPart.metadata = result.metadata;
175
+ }
176
+ }
177
+ catch (error) {
178
+ if (onFileError) {
179
+ yield onFileError(uploadId, currentPart.fieldName, currentPart.fileName, error);
180
+ }
181
+ currentPart = null;
182
+ continue;
183
+ }
184
+ }
185
+ // Add to ctx.files
186
+ ctx.files.set(currentPart.fieldName, {
187
+ name: currentPart.fileName,
188
+ type: currentPart.contentType,
189
+ size: 0, // Will be updated as we read
190
+ customFilename: currentPart.customFilename,
191
+ metadata: currentPart.metadata,
192
+ });
193
+ }
194
+ else {
195
+ // This is a text field
196
+ fieldCount++;
197
+ if (fieldCount > maxFields) {
198
+ throw new Error(`Maximum number of fields (${maxFields}) exceeded`);
199
+ }
200
+ }
201
+ }
202
+ if (currentPart && currentPart.isProcessing) {
203
+ // Process part data until we hit a boundary
204
+ const boundaryIndex = findSequence(buffer, boundaryBytes);
205
+ if (boundaryIndex !== -1) {
206
+ // We found the next boundary
207
+ // Check for CRLF before boundary (it should be there)
208
+ let dataEnd = boundaryIndex;
209
+ if (boundaryIndex >= 2) {
210
+ // Check if there's a CRLF before the boundary
211
+ if (buffer[boundaryIndex - 2] === 13 &&
212
+ buffer[boundaryIndex - 1] === 10) {
213
+ dataEnd = boundaryIndex - 2; // Exclude the CRLF
214
+ }
215
+ }
216
+ const partData = buffer.slice(0, dataEnd);
217
+ if (currentPart.fileName) {
218
+ // Process file chunk
219
+ if (partData.length > 0) {
220
+ currentPart.bytesRead += partData.length;
221
+ // Check file size limit
222
+ if (currentPart.bytesRead > maxFileSize) {
223
+ throw new Error(`File ${currentPart.fileName} exceeds maximum size of ${maxFileSize} bytes`);
224
+ }
225
+ // Update file size in context
226
+ const file = ctx.files.get(currentPart.fieldName);
227
+ file.size = currentPart.bytesRead;
228
+ // Call onFileChunk
229
+ if (onFileChunk) {
230
+ yield onFileChunk(uploadId, currentPart.fieldName, currentPart.fileName, partData, currentPart.bytesRead - partData.length, true);
231
+ }
232
+ // Call onFileComplete
233
+ if (onFileComplete) {
234
+ yield onFileComplete(uploadId, currentPart.fieldName, currentPart.fileName, currentPart.bytesRead, currentPart.customFilename, currentPart.metadata);
235
+ }
236
+ }
237
+ }
238
+ else {
239
+ // Process text field
240
+ if (partData.length > 0) {
241
+ const value = new TextDecoder().decode(partData);
242
+ // Add to context
243
+ ctx.fields.set(currentPart.fieldName, value);
244
+ // Call onField
245
+ if (onField) {
246
+ yield onField(uploadId, currentPart.fieldName, value);
247
+ }
248
+ }
249
+ }
250
+ // Move buffer past processed data and boundary
251
+ buffer = buffer.slice(boundaryIndex);
252
+ currentPart = null;
253
+ processed = true;
254
+ }
255
+ else {
256
+ // No boundary found yet
257
+ // Process what we have in buffer (but leave enough bytes for a potential boundary)
258
+ const minBoundaryLength = boundaryBytes.length;
259
+ // Only process if we have significantly more data than boundary length
260
+ if (buffer.length > minBoundaryLength * 2) {
261
+ // Process chunks, but keep enough in buffer to detect boundary
262
+ const chunkSize = buffer.length - minBoundaryLength;
263
+ if (currentPart.fileName && chunkSize > 0) {
264
+ const partData = buffer.slice(0, chunkSize);
265
+ currentPart.bytesRead += partData.length;
266
+ // Check file size limit
267
+ if (currentPart.bytesRead > maxFileSize) {
268
+ throw new Error(`File ${currentPart.fileName} exceeds maximum size of ${maxFileSize} bytes`);
269
+ }
270
+ // Update file size in context
271
+ const file = ctx.files.get(currentPart.fieldName);
272
+ file.size = currentPart.bytesRead;
273
+ // Call onFileChunk
274
+ if (onFileChunk) {
275
+ yield onFileChunk(uploadId, currentPart.fieldName, currentPart.fileName, partData, currentPart.bytesRead - partData.length, false);
276
+ }
277
+ // Move buffer past processed data
278
+ buffer = buffer.slice(chunkSize);
279
+ processed = true;
280
+ }
281
+ }
282
+ }
283
+ }
284
+ } while (processed);
285
+ }
286
+ // Process any remaining data in buffer (for the last part)
287
+ if (currentPart && buffer.length > 0) {
288
+ if (currentPart.fileName) {
289
+ // Process remaining file data
290
+ currentPart.bytesRead += buffer.length;
291
+ // Check file size limit
292
+ if (currentPart.bytesRead > maxFileSize) {
293
+ throw new Error(`File ${currentPart.fileName} exceeds maximum size of ${maxFileSize} bytes`);
294
+ }
295
+ // Update file size in context
296
+ const file = ctx.files.get(currentPart.fieldName);
297
+ file.size = currentPart.bytesRead;
298
+ // Call onFileChunk for last chunk
299
+ if (onFileChunk) {
300
+ yield onFileChunk(uploadId, currentPart.fieldName, currentPart.fileName, buffer, currentPart.bytesRead - buffer.length, true);
301
+ }
302
+ // Call onFileComplete
303
+ if (onFileComplete) {
304
+ yield onFileComplete(uploadId, currentPart.fieldName, currentPart.fileName, currentPart.bytesRead, currentPart.customFilename, currentPart.metadata);
305
+ }
306
+ }
307
+ else {
308
+ // Process remaining text field data
309
+ const value = new TextDecoder().decode(buffer);
310
+ // Add to context
311
+ ctx.fields.set(currentPart.fieldName, value);
312
+ // Call onField
313
+ if (onField) {
314
+ yield onField(uploadId, currentPart.fieldName, value);
315
+ }
316
+ }
317
+ }
318
+ // Notify upload completion
319
+ if (onUploadComplete) {
320
+ yield onUploadComplete(uploadId, true);
321
+ }
322
+ }
323
+ catch (error) {
324
+ // Notify upload completion with failure
325
+ if (onUploadComplete) {
326
+ yield onUploadComplete(uploadId, false).catch(() => { });
327
+ }
328
+ // Call error handler
329
+ if (onError) {
330
+ yield onError(uploadId, error).catch(() => { });
331
+ }
332
+ console.error("Upload parsing error:", error);
333
+ if (error.message.includes("exceeds maximum")) {
334
+ return (0, helpers_js_1.status)(413, error.message);
335
+ }
336
+ if (error.message.includes("not allowed")) {
337
+ return (0, helpers_js_1.status)(415, error.message);
338
+ }
339
+ if (error.message.includes("exceeded")) {
340
+ return (0, helpers_js_1.status)(400, error.message);
341
+ }
342
+ return (0, helpers_js_1.status)(400, "Failed to parse upload");
343
+ }
344
+ });
345
+ };
346
+ exports.parseUploadStreaming = parseUploadStreaming;
347
+ /**
348
+ * Helper function to find a byte sequence within a buffer.
349
+ * Performs a linear search for the sequence in the buffer.
350
+ *
351
+ * @private
352
+ * @param {Uint8Array} buffer - The buffer to search within
353
+ * @param {Uint8Array} sequence - The byte sequence to find
354
+ * @returns {number} The index of the sequence, or -1 if not found
355
+ */
356
+ function findSequence(buffer, sequence) {
357
+ if (buffer.length < sequence.length)
358
+ return -1;
359
+ // Use a more efficient search algorithm for large buffers
360
+ for (let i = 0; i <= buffer.length - sequence.length; i++) {
361
+ let found = true;
362
+ for (let j = 0; j < sequence.length; j++) {
363
+ if (buffer[i + j] !== sequence[j]) {
364
+ found = false;
365
+ break;
366
+ }
367
+ }
368
+ if (found)
369
+ return i;
370
+ }
371
+ return -1;
372
+ }
373
+ /**
374
+ * Helper function to parse HTTP headers from text.
375
+ *
376
+ * @private
377
+ * @param {string} headerText - Raw header text with CRLF separators
378
+ * @returns {Map<string, string>} Map of lowercase header names to values
379
+ */
380
+ function parseHeaders(headerText) {
381
+ const headers = new Map();
382
+ const lines = headerText.split("\r\n");
383
+ for (const line of lines) {
384
+ const colonIndex = line.indexOf(":");
385
+ if (colonIndex !== -1) {
386
+ const key = line.slice(0, colonIndex).trim().toLowerCase();
387
+ const value = line.slice(colonIndex + 1).trim();
388
+ headers.set(key, value);
389
+ }
390
+ }
391
+ return headers;
392
+ }
393
+ /**
394
+ * Helper function to parse content-disposition header parameters.
395
+ *
396
+ * @private
397
+ * @param {string} disposition - Content-disposition header value
398
+ * @returns {Map<string, string>} Map of parameter names to values
399
+ */
400
+ function parseDisposition(disposition) {
401
+ const params = new Map();
402
+ const parts = disposition.split(";").map((p) => p.trim());
403
+ for (let i = 1; i < parts.length; i++) {
404
+ const part = parts[i];
405
+ const eqIndex = part.indexOf("=");
406
+ if (eqIndex !== -1) {
407
+ let key = part.slice(0, eqIndex).trim();
408
+ let value = part.slice(eqIndex + 1).trim();
409
+ if (value.startsWith('"') && value.endsWith('"')) {
410
+ value = value.slice(1, -1);
411
+ }
412
+ params.set(key, value);
413
+ }
414
+ }
415
+ return params;
416
+ }
417
+ //# sourceMappingURL=upload-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload-stream.js","sourceRoot":"","sources":["../../src/upload-stream.ts"],"names":[],"mappings":"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"}