sprint-es 0.0.163 → 0.0.165
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/dist/cjs/index.cjs +52 -37
- package/dist/cjs/modules/schemas/index.cjs +88 -88
- package/dist/esm/index.js +52 -37
- package/dist/esm/modules/schemas/index.js +88 -88
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/modules/schemas/index.d.ts +6 -21
- package/dist/types/modules/schemas/index.d.ts.map +1 -1
- package/dist/types/modules/schemas/types.d.ts +28 -3
- package/dist/types/modules/schemas/types.d.ts.map +1 -1
- package/dist/types/sprint.d.ts +1 -10
- package/dist/types/sprint.d.ts.map +1 -1
- package/dist/types/types.d.ts +1 -13
- package/dist/types/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -468,25 +468,38 @@ class Sprint {
|
|
|
468
468
|
for (const layer of router.stack) {
|
|
469
469
|
if (!layer.route) continue;
|
|
470
470
|
for (const routeLayer of layer.route.stack) {
|
|
471
|
-
const
|
|
472
|
-
const
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
471
|
+
const handlers = Array.isArray(routeLayer.handle) ? routeLayer.handle : [routeLayer.handle];
|
|
472
|
+
for (const handler of handlers) {
|
|
473
|
+
const handlerSchema = handler.__sprintRouteSchema;
|
|
474
|
+
if (handlerSchema?.files && typeof handlerSchema.files === "object" && !Array.isArray(handlerSchema.files)) {
|
|
475
|
+
const fileFields = Object.keys(handlerSchema.files);
|
|
476
|
+
const hasStreaming = handler?.hasStreamingFiles ? handler.hasStreamingFiles() : false;
|
|
477
|
+
if (hasStreaming) {
|
|
478
|
+
fileUploadMiddleware = this.streamUpload();
|
|
479
|
+
break;
|
|
480
|
+
} else if (fileFields.length > 0) {
|
|
481
|
+
fileUploadMiddleware = this.uploadFiles(fileFields);
|
|
482
|
+
break;
|
|
483
|
+
}
|
|
478
484
|
}
|
|
479
485
|
}
|
|
486
|
+
if (fileUploadMiddleware) break;
|
|
480
487
|
}
|
|
481
488
|
if (fileUploadMiddleware) break;
|
|
482
489
|
}
|
|
483
490
|
if (routeMiddlewares.length > 0) {
|
|
484
|
-
if (fileUploadMiddleware)
|
|
485
|
-
|
|
491
|
+
if (fileUploadMiddleware) {
|
|
492
|
+
this.app.use(finalRoute, fileUploadMiddleware, ...routeMiddlewares, router);
|
|
493
|
+
} else {
|
|
494
|
+
this.app.use(finalRoute, ...routeMiddlewares, router);
|
|
495
|
+
}
|
|
486
496
|
if (isVerbose) console.log(`[Sprint] Loaded route: ${finalRoute} -> ${filePath} (with ${routeMiddlewares.length} middleware(s))`);
|
|
487
497
|
} else {
|
|
488
|
-
if (fileUploadMiddleware)
|
|
489
|
-
|
|
498
|
+
if (fileUploadMiddleware) {
|
|
499
|
+
this.app.use(finalRoute, fileUploadMiddleware, router);
|
|
500
|
+
} else {
|
|
501
|
+
this.app.use(finalRoute, router);
|
|
502
|
+
}
|
|
490
503
|
if (isVerbose) console.log(`[Sprint] Loaded route: ${finalRoute} -> ${filePath}`);
|
|
491
504
|
}
|
|
492
505
|
this.counters.routes += router.stack.length;
|
|
@@ -859,34 +872,36 @@ class Sprint {
|
|
|
859
872
|
return this.memoryUpload.array(fieldNames);
|
|
860
873
|
}
|
|
861
874
|
streamUpload(options) {
|
|
862
|
-
return (req, res) => {
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
});
|
|
879
|
-
bb.on("field", (fieldName, val) => {
|
|
880
|
-
fields[fieldName] = val;
|
|
881
|
-
});
|
|
882
|
-
bb.on("finish", () => {
|
|
883
|
-
resolve({ files, fields });
|
|
884
|
-
});
|
|
885
|
-
bb.on("error", (err) => {
|
|
886
|
-
reject(err);
|
|
875
|
+
return (req, res, next) => {
|
|
876
|
+
const bb = busboy({
|
|
877
|
+
headers: req.headers,
|
|
878
|
+
limits: options?.limits
|
|
879
|
+
});
|
|
880
|
+
const files = {};
|
|
881
|
+
bb.on("file", (fieldName, file, info) => {
|
|
882
|
+
if (!files[fieldName]) files[fieldName] = [];
|
|
883
|
+
files[fieldName].push({
|
|
884
|
+
fieldname: fieldName,
|
|
885
|
+
originalname: info.filename,
|
|
886
|
+
encoding: info.encoding,
|
|
887
|
+
mimetype: info.mimeType,
|
|
888
|
+
size: 0,
|
|
889
|
+
buffer: void 0,
|
|
890
|
+
file
|
|
887
891
|
});
|
|
888
|
-
req.pipe(bb);
|
|
889
892
|
});
|
|
893
|
+
bb.on("field", (fieldName, val) => {
|
|
894
|
+
if (!req.body) req.body = {};
|
|
895
|
+
req.body[fieldName] = val;
|
|
896
|
+
});
|
|
897
|
+
bb.on("finish", () => {
|
|
898
|
+
req.files = files;
|
|
899
|
+
next();
|
|
900
|
+
});
|
|
901
|
+
bb.on("error", (err) => {
|
|
902
|
+
next(err);
|
|
903
|
+
});
|
|
904
|
+
req.pipe(bb);
|
|
890
905
|
};
|
|
891
906
|
}
|
|
892
907
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const stream = require("stream");
|
|
3
4
|
const zod = require("zod");
|
|
4
5
|
function normalizeExtensions(ext) {
|
|
5
6
|
if (!ext) return [];
|
|
@@ -9,48 +10,84 @@ function normalizeMimeTypes(mime) {
|
|
|
9
10
|
if (!mime) return [];
|
|
10
11
|
return (Array.isArray(mime) ? mime : [mime]).map((m) => m.toLowerCase());
|
|
11
12
|
}
|
|
12
|
-
function createFileSchema(options = {}) {
|
|
13
|
+
function createFileSchema(options = {}, isStream = false) {
|
|
13
14
|
const extensions = normalizeExtensions(options.ext);
|
|
14
15
|
const mimeTypes = normalizeMimeTypes(options.mimeType);
|
|
15
|
-
const
|
|
16
|
+
const finalIsStream = options._isStream || isStream;
|
|
17
|
+
const baseSchema = {
|
|
16
18
|
fieldname: zod.z.string(),
|
|
17
19
|
originalname: zod.z.string(),
|
|
18
20
|
encoding: zod.z.string(),
|
|
19
21
|
mimetype: zod.z.string(),
|
|
20
|
-
size: zod.z.number()
|
|
21
|
-
|
|
22
|
-
});
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
22
|
+
size: zod.z.number()
|
|
23
|
+
};
|
|
24
|
+
const extendedSchema = finalIsStream ? { ...baseSchema, file: zod.z.instanceof(stream.Readable).optional() } : { ...baseSchema, buffer: zod.z.instanceof(Buffer).optional() };
|
|
25
|
+
const fileSchema = zod.z.object(extendedSchema);
|
|
26
|
+
let schemaWithValidations = fileSchema;
|
|
27
|
+
if (extensions.length > 0) {
|
|
28
|
+
schemaWithValidations = schemaWithValidations.refine(
|
|
29
|
+
(file) => {
|
|
30
|
+
const fileExt = file.originalname.toLowerCase().substring(file.originalname.lastIndexOf("."));
|
|
31
|
+
return extensions.includes(fileExt);
|
|
32
|
+
},
|
|
33
|
+
{ message: `Invalid file extension. Allowed: ${extensions.join(", ")}`, path: ["originalname"] }
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
if (mimeTypes.length > 0) {
|
|
37
|
+
schemaWithValidations = schemaWithValidations.refine(
|
|
38
|
+
(file) => mimeTypes.includes(file.mimetype.toLowerCase()),
|
|
39
|
+
{ message: `Invalid mime type. Allowed: ${mimeTypes.join(", ")}`, path: ["mimetype"] }
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
if (options.maxSize !== void 0) {
|
|
43
|
+
schemaWithValidations = schemaWithValidations.refine(
|
|
44
|
+
(file) => file.size <= options.maxSize,
|
|
45
|
+
{ message: `File size exceeds maximum of ${options.maxSize} bytes`, path: ["size"] }
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
if (options.minSize !== void 0) {
|
|
49
|
+
schemaWithValidations = schemaWithValidations.refine(
|
|
50
|
+
(file) => file.size >= options.minSize,
|
|
51
|
+
{ message: `File size must be at least ${options.minSize} bytes`, path: ["size"] }
|
|
52
|
+
);
|
|
53
|
+
}
|
|
49
54
|
const chainedSchema = Object.create(schemaWithValidations);
|
|
50
|
-
chainedSchema.format = (ext) => createFileSchema({ ...options, ext: normalizeExtensions(ext) });
|
|
51
|
-
chainedSchema.mimeType = (mime) => createFileSchema({ ...options, mimeType: normalizeMimeTypes(mime) });
|
|
52
|
-
chainedSchema.maxSize = (size) => createFileSchema({ ...options, maxSize: size });
|
|
53
|
-
chainedSchema.minSize = (size) => createFileSchema({ ...options, minSize: size });
|
|
55
|
+
chainedSchema.format = (ext) => createFileSchema({ ...options, ext: normalizeExtensions(ext), _isStream: finalIsStream }, finalIsStream);
|
|
56
|
+
chainedSchema.mimeType = (mime) => createFileSchema({ ...options, mimeType: normalizeMimeTypes(mime), _isStream: finalIsStream }, finalIsStream);
|
|
57
|
+
chainedSchema.maxSize = (size) => createFileSchema({ ...options, maxSize: size, _isStream: finalIsStream }, finalIsStream);
|
|
58
|
+
chainedSchema.minSize = (size) => createFileSchema({ ...options, minSize: size, _isStream: finalIsStream }, finalIsStream);
|
|
59
|
+
chainedSchema.stream = () => createFileSchema({ ...options, _isStream: true }, true);
|
|
60
|
+
chainedSchema.image = () => createFileSchema({
|
|
61
|
+
mimeType: ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml"],
|
|
62
|
+
ext: ["jpg", "jpeg", "png", "gif", "webp", "svg"],
|
|
63
|
+
_isStream: finalIsStream
|
|
64
|
+
}, finalIsStream);
|
|
65
|
+
chainedSchema.document = () => createFileSchema({
|
|
66
|
+
mimeType: ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "text/plain"],
|
|
67
|
+
ext: ["pdf", "doc", "docx", "txt"],
|
|
68
|
+
_isStream: finalIsStream
|
|
69
|
+
}, finalIsStream);
|
|
70
|
+
chainedSchema.video = () => createFileSchema({
|
|
71
|
+
mimeType: ["video/mp4", "video/webm", "video/ogg"],
|
|
72
|
+
ext: ["mp4", "webm", "ogg"],
|
|
73
|
+
_isStream: finalIsStream
|
|
74
|
+
}, finalIsStream);
|
|
75
|
+
chainedSchema.audio = () => createFileSchema({
|
|
76
|
+
mimeType: ["audio/mpeg", "audio/wav", "audio/ogg", "audio/webm"],
|
|
77
|
+
ext: ["mp3", "wav", "ogg", "webm"],
|
|
78
|
+
_isStream: finalIsStream
|
|
79
|
+
}, finalIsStream);
|
|
80
|
+
chainedSchema.archive = () => createFileSchema({
|
|
81
|
+
mimeType: ["application/zip", "application/x-rar-compressed", "application/x-7z-compressed"],
|
|
82
|
+
ext: ["zip", "rar", "7z"],
|
|
83
|
+
_isStream: finalIsStream
|
|
84
|
+
}, finalIsStream);
|
|
85
|
+
chainedSchema.any = () => createFileSchema({ ...options, _isStream: finalIsStream }, finalIsStream);
|
|
86
|
+
chainedSchema._isStream = finalIsStream;
|
|
87
|
+
chainedSchema._extensions = extensions;
|
|
88
|
+
chainedSchema._mimeTypes = mimeTypes;
|
|
89
|
+
chainedSchema._maxSize = options.maxSize;
|
|
90
|
+
chainedSchema._minSize = options.minSize;
|
|
54
91
|
return chainedSchema;
|
|
55
92
|
}
|
|
56
93
|
function createFilesArraySchema(fieldName, options = {}) {
|
|
@@ -60,56 +97,19 @@ function createFilesArraySchema(fieldName, options = {}) {
|
|
|
60
97
|
});
|
|
61
98
|
}
|
|
62
99
|
const fileValidators = {
|
|
63
|
-
format: (ext) => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
},
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
},
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
},
|
|
77
|
-
image: () => {
|
|
78
|
-
return createFileSchema({
|
|
79
|
-
mimeType: ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml"],
|
|
80
|
-
ext: ["jpg", "jpeg", "png", "gif", "webp", "svg"]
|
|
81
|
-
});
|
|
82
|
-
},
|
|
83
|
-
document: () => {
|
|
84
|
-
return createFileSchema({
|
|
85
|
-
mimeType: ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "text/plain"],
|
|
86
|
-
ext: ["pdf", "doc", "docx", "txt"]
|
|
87
|
-
});
|
|
88
|
-
},
|
|
89
|
-
video: () => {
|
|
90
|
-
return createFileSchema({
|
|
91
|
-
mimeType: ["video/mp4", "video/webm", "video/ogg"],
|
|
92
|
-
ext: ["mp4", "webm", "ogg"]
|
|
93
|
-
});
|
|
94
|
-
},
|
|
95
|
-
audio: () => {
|
|
96
|
-
return createFileSchema({
|
|
97
|
-
mimeType: ["audio/mpeg", "audio/wav", "audio/ogg", "audio/webm"],
|
|
98
|
-
ext: ["mp3", "wav", "ogg", "webm"]
|
|
99
|
-
});
|
|
100
|
-
},
|
|
101
|
-
archive: () => {
|
|
102
|
-
return createFileSchema({
|
|
103
|
-
mimeType: ["application/zip", "application/x-rar-compressed", "application/x-7z-compressed"],
|
|
104
|
-
ext: ["zip", "rar", "7z"]
|
|
105
|
-
});
|
|
106
|
-
},
|
|
107
|
-
any: () => {
|
|
108
|
-
return createFileSchema({});
|
|
109
|
-
},
|
|
110
|
-
field: (fieldName, options) => {
|
|
111
|
-
return createFilesArraySchema(fieldName, options);
|
|
112
|
-
}
|
|
100
|
+
format: (ext) => createFileSchema({ ext: normalizeExtensions(ext) }),
|
|
101
|
+
mimeType: (mimeType) => createFileSchema({ mimeType: normalizeMimeTypes(mimeType) }),
|
|
102
|
+
maxSize: (maxSize) => createFileSchema({ maxSize }),
|
|
103
|
+
minSize: (minSize) => createFileSchema({ minSize }),
|
|
104
|
+
stream: () => createFileSchema({ _isStream: true }, true),
|
|
105
|
+
image: () => createFileSchema({ mimeType: ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml"], ext: ["jpg", "jpeg", "png", "gif", "webp", "svg"] }),
|
|
106
|
+
document: () => createFileSchema({ mimeType: ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "text/plain"], ext: ["pdf", "doc", "docx", "txt"] }),
|
|
107
|
+
video: () => createFileSchema({ mimeType: ["video/mp4", "video/webm", "video/ogg"], ext: ["mp4", "webm", "ogg"] }),
|
|
108
|
+
audio: () => createFileSchema({ mimeType: ["audio/mpeg", "audio/wav", "audio/ogg", "audio/webm"], ext: ["mp3", "wav", "ogg", "webm"] }),
|
|
109
|
+
archive: () => createFileSchema({ mimeType: ["application/zip", "application/x-rar-compressed", "application/x-7z-compressed"], ext: ["zip", "rar", "7z"] }),
|
|
110
|
+
any: () => createFileSchema({}),
|
|
111
|
+
field: (fieldName, options) => createFilesArraySchema(fieldName, options),
|
|
112
|
+
_isStream: false
|
|
113
113
|
};
|
|
114
114
|
function normalizeHeadersSchema(schema) {
|
|
115
115
|
const shape = schema.shape ?? schema._def?.shape?.();
|
|
@@ -155,6 +155,7 @@ function parseSchema(schema, data) {
|
|
|
155
155
|
function defineRouteSchema(schema) {
|
|
156
156
|
const headersSchema = schema.headers ? normalizeHeadersSchema(schema.headers) : null;
|
|
157
157
|
const fileFields = schema.files ? Object.keys(schema.files) : [];
|
|
158
|
+
const hasStreaming = !!(schema.files && typeof schema.files === "object" && Object.values(schema.files).some((f) => !!f._isStream));
|
|
158
159
|
const middleware = (req, res, next) => {
|
|
159
160
|
const errors = [];
|
|
160
161
|
const method = req.method.toUpperCase();
|
|
@@ -183,9 +184,7 @@ function defineRouteSchema(schema) {
|
|
|
183
184
|
const isOptional = fieldSchema.isOptional ? fieldSchema.isOptional() : false;
|
|
184
185
|
if (filesArray.length > 0 || isOptional) {
|
|
185
186
|
const result = parseSchema(fieldSchema, filesArray);
|
|
186
|
-
if (!result.success) {
|
|
187
|
-
errors.push(...result.errors.map((e) => ({ location: "files", path: fieldName, message: `${e.path || fieldName}: ${e.message}` })));
|
|
188
|
-
}
|
|
187
|
+
if (!result.success) errors.push(...result.errors.map((e) => ({ location: "files", path: fieldName, message: `${e.path || fieldName}: ${e.message}` })));
|
|
189
188
|
}
|
|
190
189
|
}
|
|
191
190
|
}
|
|
@@ -229,6 +228,7 @@ function defineRouteSchema(schema) {
|
|
|
229
228
|
};
|
|
230
229
|
middleware.__sprintRouteSchema = schema;
|
|
231
230
|
middleware.getFileFields = () => fileFields;
|
|
231
|
+
middleware.hasStreamingFiles = () => hasStreaming || false;
|
|
232
232
|
return middleware;
|
|
233
233
|
}
|
|
234
234
|
exports.createFileSchema = createFileSchema;
|
package/dist/esm/index.js
CHANGED
|
@@ -443,25 +443,38 @@ class Sprint {
|
|
|
443
443
|
for (const layer of router.stack) {
|
|
444
444
|
if (!layer.route) continue;
|
|
445
445
|
for (const routeLayer of layer.route.stack) {
|
|
446
|
-
const
|
|
447
|
-
const
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
446
|
+
const handlers = Array.isArray(routeLayer.handle) ? routeLayer.handle : [routeLayer.handle];
|
|
447
|
+
for (const handler of handlers) {
|
|
448
|
+
const handlerSchema = handler.__sprintRouteSchema;
|
|
449
|
+
if (handlerSchema?.files && typeof handlerSchema.files === "object" && !Array.isArray(handlerSchema.files)) {
|
|
450
|
+
const fileFields = Object.keys(handlerSchema.files);
|
|
451
|
+
const hasStreaming = handler?.hasStreamingFiles ? handler.hasStreamingFiles() : false;
|
|
452
|
+
if (hasStreaming) {
|
|
453
|
+
fileUploadMiddleware = this.streamUpload();
|
|
454
|
+
break;
|
|
455
|
+
} else if (fileFields.length > 0) {
|
|
456
|
+
fileUploadMiddleware = this.uploadFiles(fileFields);
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
453
459
|
}
|
|
454
460
|
}
|
|
461
|
+
if (fileUploadMiddleware) break;
|
|
455
462
|
}
|
|
456
463
|
if (fileUploadMiddleware) break;
|
|
457
464
|
}
|
|
458
465
|
if (routeMiddlewares.length > 0) {
|
|
459
|
-
if (fileUploadMiddleware)
|
|
460
|
-
|
|
466
|
+
if (fileUploadMiddleware) {
|
|
467
|
+
this.app.use(finalRoute, fileUploadMiddleware, ...routeMiddlewares, router);
|
|
468
|
+
} else {
|
|
469
|
+
this.app.use(finalRoute, ...routeMiddlewares, router);
|
|
470
|
+
}
|
|
461
471
|
if (isVerbose) console.log(`[Sprint] Loaded route: ${finalRoute} -> ${filePath} (with ${routeMiddlewares.length} middleware(s))`);
|
|
462
472
|
} else {
|
|
463
|
-
if (fileUploadMiddleware)
|
|
464
|
-
|
|
473
|
+
if (fileUploadMiddleware) {
|
|
474
|
+
this.app.use(finalRoute, fileUploadMiddleware, router);
|
|
475
|
+
} else {
|
|
476
|
+
this.app.use(finalRoute, router);
|
|
477
|
+
}
|
|
465
478
|
if (isVerbose) console.log(`[Sprint] Loaded route: ${finalRoute} -> ${filePath}`);
|
|
466
479
|
}
|
|
467
480
|
this.counters.routes += router.stack.length;
|
|
@@ -834,34 +847,36 @@ class Sprint {
|
|
|
834
847
|
return this.memoryUpload.array(fieldNames);
|
|
835
848
|
}
|
|
836
849
|
streamUpload(options) {
|
|
837
|
-
return (req, res) => {
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
});
|
|
854
|
-
bb.on("field", (fieldName, val) => {
|
|
855
|
-
fields[fieldName] = val;
|
|
856
|
-
});
|
|
857
|
-
bb.on("finish", () => {
|
|
858
|
-
resolve({ files, fields });
|
|
859
|
-
});
|
|
860
|
-
bb.on("error", (err) => {
|
|
861
|
-
reject(err);
|
|
850
|
+
return (req, res, next) => {
|
|
851
|
+
const bb = busboy({
|
|
852
|
+
headers: req.headers,
|
|
853
|
+
limits: options?.limits
|
|
854
|
+
});
|
|
855
|
+
const files = {};
|
|
856
|
+
bb.on("file", (fieldName, file, info) => {
|
|
857
|
+
if (!files[fieldName]) files[fieldName] = [];
|
|
858
|
+
files[fieldName].push({
|
|
859
|
+
fieldname: fieldName,
|
|
860
|
+
originalname: info.filename,
|
|
861
|
+
encoding: info.encoding,
|
|
862
|
+
mimetype: info.mimeType,
|
|
863
|
+
size: 0,
|
|
864
|
+
buffer: void 0,
|
|
865
|
+
file
|
|
862
866
|
});
|
|
863
|
-
req.pipe(bb);
|
|
864
867
|
});
|
|
868
|
+
bb.on("field", (fieldName, val) => {
|
|
869
|
+
if (!req.body) req.body = {};
|
|
870
|
+
req.body[fieldName] = val;
|
|
871
|
+
});
|
|
872
|
+
bb.on("finish", () => {
|
|
873
|
+
req.files = files;
|
|
874
|
+
next();
|
|
875
|
+
});
|
|
876
|
+
bb.on("error", (err) => {
|
|
877
|
+
next(err);
|
|
878
|
+
});
|
|
879
|
+
req.pipe(bb);
|
|
865
880
|
};
|
|
866
881
|
}
|
|
867
882
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Readable } from "stream";
|
|
1
2
|
import { z } from "zod";
|
|
2
3
|
function normalizeExtensions(ext) {
|
|
3
4
|
if (!ext) return [];
|
|
@@ -7,48 +8,84 @@ function normalizeMimeTypes(mime) {
|
|
|
7
8
|
if (!mime) return [];
|
|
8
9
|
return (Array.isArray(mime) ? mime : [mime]).map((m) => m.toLowerCase());
|
|
9
10
|
}
|
|
10
|
-
function createFileSchema(options = {}) {
|
|
11
|
+
function createFileSchema(options = {}, isStream = false) {
|
|
11
12
|
const extensions = normalizeExtensions(options.ext);
|
|
12
13
|
const mimeTypes = normalizeMimeTypes(options.mimeType);
|
|
13
|
-
const
|
|
14
|
+
const finalIsStream = options._isStream || isStream;
|
|
15
|
+
const baseSchema = {
|
|
14
16
|
fieldname: z.string(),
|
|
15
17
|
originalname: z.string(),
|
|
16
18
|
encoding: z.string(),
|
|
17
19
|
mimetype: z.string(),
|
|
18
|
-
size: z.number()
|
|
19
|
-
|
|
20
|
-
});
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
20
|
+
size: z.number()
|
|
21
|
+
};
|
|
22
|
+
const extendedSchema = finalIsStream ? { ...baseSchema, file: z.instanceof(Readable).optional() } : { ...baseSchema, buffer: z.instanceof(Buffer).optional() };
|
|
23
|
+
const fileSchema = z.object(extendedSchema);
|
|
24
|
+
let schemaWithValidations = fileSchema;
|
|
25
|
+
if (extensions.length > 0) {
|
|
26
|
+
schemaWithValidations = schemaWithValidations.refine(
|
|
27
|
+
(file) => {
|
|
28
|
+
const fileExt = file.originalname.toLowerCase().substring(file.originalname.lastIndexOf("."));
|
|
29
|
+
return extensions.includes(fileExt);
|
|
30
|
+
},
|
|
31
|
+
{ message: `Invalid file extension. Allowed: ${extensions.join(", ")}`, path: ["originalname"] }
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
if (mimeTypes.length > 0) {
|
|
35
|
+
schemaWithValidations = schemaWithValidations.refine(
|
|
36
|
+
(file) => mimeTypes.includes(file.mimetype.toLowerCase()),
|
|
37
|
+
{ message: `Invalid mime type. Allowed: ${mimeTypes.join(", ")}`, path: ["mimetype"] }
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
if (options.maxSize !== void 0) {
|
|
41
|
+
schemaWithValidations = schemaWithValidations.refine(
|
|
42
|
+
(file) => file.size <= options.maxSize,
|
|
43
|
+
{ message: `File size exceeds maximum of ${options.maxSize} bytes`, path: ["size"] }
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
if (options.minSize !== void 0) {
|
|
47
|
+
schemaWithValidations = schemaWithValidations.refine(
|
|
48
|
+
(file) => file.size >= options.minSize,
|
|
49
|
+
{ message: `File size must be at least ${options.minSize} bytes`, path: ["size"] }
|
|
50
|
+
);
|
|
51
|
+
}
|
|
47
52
|
const chainedSchema = Object.create(schemaWithValidations);
|
|
48
|
-
chainedSchema.format = (ext) => createFileSchema({ ...options, ext: normalizeExtensions(ext) });
|
|
49
|
-
chainedSchema.mimeType = (mime) => createFileSchema({ ...options, mimeType: normalizeMimeTypes(mime) });
|
|
50
|
-
chainedSchema.maxSize = (size) => createFileSchema({ ...options, maxSize: size });
|
|
51
|
-
chainedSchema.minSize = (size) => createFileSchema({ ...options, minSize: size });
|
|
53
|
+
chainedSchema.format = (ext) => createFileSchema({ ...options, ext: normalizeExtensions(ext), _isStream: finalIsStream }, finalIsStream);
|
|
54
|
+
chainedSchema.mimeType = (mime) => createFileSchema({ ...options, mimeType: normalizeMimeTypes(mime), _isStream: finalIsStream }, finalIsStream);
|
|
55
|
+
chainedSchema.maxSize = (size) => createFileSchema({ ...options, maxSize: size, _isStream: finalIsStream }, finalIsStream);
|
|
56
|
+
chainedSchema.minSize = (size) => createFileSchema({ ...options, minSize: size, _isStream: finalIsStream }, finalIsStream);
|
|
57
|
+
chainedSchema.stream = () => createFileSchema({ ...options, _isStream: true }, true);
|
|
58
|
+
chainedSchema.image = () => createFileSchema({
|
|
59
|
+
mimeType: ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml"],
|
|
60
|
+
ext: ["jpg", "jpeg", "png", "gif", "webp", "svg"],
|
|
61
|
+
_isStream: finalIsStream
|
|
62
|
+
}, finalIsStream);
|
|
63
|
+
chainedSchema.document = () => createFileSchema({
|
|
64
|
+
mimeType: ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "text/plain"],
|
|
65
|
+
ext: ["pdf", "doc", "docx", "txt"],
|
|
66
|
+
_isStream: finalIsStream
|
|
67
|
+
}, finalIsStream);
|
|
68
|
+
chainedSchema.video = () => createFileSchema({
|
|
69
|
+
mimeType: ["video/mp4", "video/webm", "video/ogg"],
|
|
70
|
+
ext: ["mp4", "webm", "ogg"],
|
|
71
|
+
_isStream: finalIsStream
|
|
72
|
+
}, finalIsStream);
|
|
73
|
+
chainedSchema.audio = () => createFileSchema({
|
|
74
|
+
mimeType: ["audio/mpeg", "audio/wav", "audio/ogg", "audio/webm"],
|
|
75
|
+
ext: ["mp3", "wav", "ogg", "webm"],
|
|
76
|
+
_isStream: finalIsStream
|
|
77
|
+
}, finalIsStream);
|
|
78
|
+
chainedSchema.archive = () => createFileSchema({
|
|
79
|
+
mimeType: ["application/zip", "application/x-rar-compressed", "application/x-7z-compressed"],
|
|
80
|
+
ext: ["zip", "rar", "7z"],
|
|
81
|
+
_isStream: finalIsStream
|
|
82
|
+
}, finalIsStream);
|
|
83
|
+
chainedSchema.any = () => createFileSchema({ ...options, _isStream: finalIsStream }, finalIsStream);
|
|
84
|
+
chainedSchema._isStream = finalIsStream;
|
|
85
|
+
chainedSchema._extensions = extensions;
|
|
86
|
+
chainedSchema._mimeTypes = mimeTypes;
|
|
87
|
+
chainedSchema._maxSize = options.maxSize;
|
|
88
|
+
chainedSchema._minSize = options.minSize;
|
|
52
89
|
return chainedSchema;
|
|
53
90
|
}
|
|
54
91
|
function createFilesArraySchema(fieldName, options = {}) {
|
|
@@ -58,56 +95,19 @@ function createFilesArraySchema(fieldName, options = {}) {
|
|
|
58
95
|
});
|
|
59
96
|
}
|
|
60
97
|
const fileValidators = {
|
|
61
|
-
format: (ext) => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
},
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
},
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
},
|
|
75
|
-
image: () => {
|
|
76
|
-
return createFileSchema({
|
|
77
|
-
mimeType: ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml"],
|
|
78
|
-
ext: ["jpg", "jpeg", "png", "gif", "webp", "svg"]
|
|
79
|
-
});
|
|
80
|
-
},
|
|
81
|
-
document: () => {
|
|
82
|
-
return createFileSchema({
|
|
83
|
-
mimeType: ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "text/plain"],
|
|
84
|
-
ext: ["pdf", "doc", "docx", "txt"]
|
|
85
|
-
});
|
|
86
|
-
},
|
|
87
|
-
video: () => {
|
|
88
|
-
return createFileSchema({
|
|
89
|
-
mimeType: ["video/mp4", "video/webm", "video/ogg"],
|
|
90
|
-
ext: ["mp4", "webm", "ogg"]
|
|
91
|
-
});
|
|
92
|
-
},
|
|
93
|
-
audio: () => {
|
|
94
|
-
return createFileSchema({
|
|
95
|
-
mimeType: ["audio/mpeg", "audio/wav", "audio/ogg", "audio/webm"],
|
|
96
|
-
ext: ["mp3", "wav", "ogg", "webm"]
|
|
97
|
-
});
|
|
98
|
-
},
|
|
99
|
-
archive: () => {
|
|
100
|
-
return createFileSchema({
|
|
101
|
-
mimeType: ["application/zip", "application/x-rar-compressed", "application/x-7z-compressed"],
|
|
102
|
-
ext: ["zip", "rar", "7z"]
|
|
103
|
-
});
|
|
104
|
-
},
|
|
105
|
-
any: () => {
|
|
106
|
-
return createFileSchema({});
|
|
107
|
-
},
|
|
108
|
-
field: (fieldName, options) => {
|
|
109
|
-
return createFilesArraySchema(fieldName, options);
|
|
110
|
-
}
|
|
98
|
+
format: (ext) => createFileSchema({ ext: normalizeExtensions(ext) }),
|
|
99
|
+
mimeType: (mimeType) => createFileSchema({ mimeType: normalizeMimeTypes(mimeType) }),
|
|
100
|
+
maxSize: (maxSize) => createFileSchema({ maxSize }),
|
|
101
|
+
minSize: (minSize) => createFileSchema({ minSize }),
|
|
102
|
+
stream: () => createFileSchema({ _isStream: true }, true),
|
|
103
|
+
image: () => createFileSchema({ mimeType: ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml"], ext: ["jpg", "jpeg", "png", "gif", "webp", "svg"] }),
|
|
104
|
+
document: () => createFileSchema({ mimeType: ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "text/plain"], ext: ["pdf", "doc", "docx", "txt"] }),
|
|
105
|
+
video: () => createFileSchema({ mimeType: ["video/mp4", "video/webm", "video/ogg"], ext: ["mp4", "webm", "ogg"] }),
|
|
106
|
+
audio: () => createFileSchema({ mimeType: ["audio/mpeg", "audio/wav", "audio/ogg", "audio/webm"], ext: ["mp3", "wav", "ogg", "webm"] }),
|
|
107
|
+
archive: () => createFileSchema({ mimeType: ["application/zip", "application/x-rar-compressed", "application/x-7z-compressed"], ext: ["zip", "rar", "7z"] }),
|
|
108
|
+
any: () => createFileSchema({}),
|
|
109
|
+
field: (fieldName, options) => createFilesArraySchema(fieldName, options),
|
|
110
|
+
_isStream: false
|
|
111
111
|
};
|
|
112
112
|
function normalizeHeadersSchema(schema) {
|
|
113
113
|
const shape = schema.shape ?? schema._def?.shape?.();
|
|
@@ -153,6 +153,7 @@ function parseSchema(schema, data) {
|
|
|
153
153
|
function defineRouteSchema(schema) {
|
|
154
154
|
const headersSchema = schema.headers ? normalizeHeadersSchema(schema.headers) : null;
|
|
155
155
|
const fileFields = schema.files ? Object.keys(schema.files) : [];
|
|
156
|
+
const hasStreaming = !!(schema.files && typeof schema.files === "object" && Object.values(schema.files).some((f) => !!f._isStream));
|
|
156
157
|
const middleware = (req, res, next) => {
|
|
157
158
|
const errors = [];
|
|
158
159
|
const method = req.method.toUpperCase();
|
|
@@ -181,9 +182,7 @@ function defineRouteSchema(schema) {
|
|
|
181
182
|
const isOptional = fieldSchema.isOptional ? fieldSchema.isOptional() : false;
|
|
182
183
|
if (filesArray.length > 0 || isOptional) {
|
|
183
184
|
const result = parseSchema(fieldSchema, filesArray);
|
|
184
|
-
if (!result.success) {
|
|
185
|
-
errors.push(...result.errors.map((e) => ({ location: "files", path: fieldName, message: `${e.path || fieldName}: ${e.message}` })));
|
|
186
|
-
}
|
|
185
|
+
if (!result.success) errors.push(...result.errors.map((e) => ({ location: "files", path: fieldName, message: `${e.path || fieldName}: ${e.message}` })));
|
|
187
186
|
}
|
|
188
187
|
}
|
|
189
188
|
}
|
|
@@ -227,6 +226,7 @@ function defineRouteSchema(schema) {
|
|
|
227
226
|
};
|
|
228
227
|
middleware.__sprintRouteSchema = schema;
|
|
229
228
|
middleware.getFileFields = () => fileFields;
|
|
229
|
+
middleware.hasStreamingFiles = () => hasStreaming || false;
|
|
230
230
|
return middleware;
|
|
231
231
|
}
|
|
232
232
|
export {
|
package/dist/types/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export { Sprint, isDevelopment, isProduction } from './sprint';
|
|
|
3
3
|
export { defineMiddleware } from './middleware';
|
|
4
4
|
export { __filename, __dirname } from './utils';
|
|
5
5
|
export type { Handler, AsyncRequestHandler, MiddlewareConfig, SprintOptions, LoadedMiddleware, AuthorizationSource, SprintRequest, SprintResponse, NextFunction } from './types';
|
|
6
|
+
export type { FileObject, SprintFiles } from './modules/schemas/types';
|
|
6
7
|
export declare const Router: () => import('express-serve-static-core').Router;
|
|
7
8
|
export default Sprint;
|
|
8
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGhD,YAAY,EAAE,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGjL,eAAO,MAAM,MAAM,kDAAwB,CAAC;AAG5C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,eAAe,MAAM,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGhD,YAAY,EAAE,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGjL,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGvE,eAAO,MAAM,MAAM,kDAAwB,CAAC;AAG5C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,eAAe,MAAM,CAAC"}
|
|
@@ -1,29 +1,13 @@
|
|
|
1
1
|
import { RequestHandler } from 'express';
|
|
2
2
|
import { z, ZodSchema as ZodSchemaType, ZodTypeDef } from 'zod';
|
|
3
|
-
import { FileObject, FileSchemaType } from './types';
|
|
3
|
+
import { FileObject, FileSchemaType, FileValidationOptions } from './types';
|
|
4
4
|
export type AuthorizationSource = `query:${string}` | `headers:${string}`;
|
|
5
5
|
export interface SprintAuthorizationOptions {
|
|
6
6
|
sources?: AuthorizationSource | AuthorizationSource[];
|
|
7
7
|
}
|
|
8
|
-
|
|
9
|
-
ext?: string | string[];
|
|
10
|
-
mimeType?: string | string[];
|
|
11
|
-
maxSize?: number;
|
|
12
|
-
minSize?: number;
|
|
13
|
-
required?: boolean;
|
|
14
|
-
}
|
|
15
|
-
declare function createFileSchema(options?: FileValidationOptions): FileSchemaType;
|
|
8
|
+
declare function createFileSchema(options?: FileValidationOptions, isStream?: boolean): FileSchemaType;
|
|
16
9
|
declare function createFilesArraySchema(fieldName: string, options?: FileValidationOptions): ZodSchemaType<FileObject[], ZodTypeDef, FileObject[]>;
|
|
17
|
-
|
|
18
|
-
image: () => FileSchemaType;
|
|
19
|
-
document: () => FileSchemaType;
|
|
20
|
-
video: () => FileSchemaType;
|
|
21
|
-
audio: () => FileSchemaType;
|
|
22
|
-
archive: () => FileSchemaType;
|
|
23
|
-
any: () => FileSchemaType;
|
|
24
|
-
field: (fieldName: string, options?: FileValidationOptions) => ZodSchemaType<FileObject[], ZodTypeDef, FileObject[]>;
|
|
25
|
-
};
|
|
26
|
-
declare const fileValidators: FileValidatorsType;
|
|
10
|
+
declare const fileValidators: FileSchemaType;
|
|
27
11
|
export declare function normalizeHeadersSchema(schema: any): any;
|
|
28
12
|
declare function createSprintAuthorizationSchema(options?: SprintAuthorizationOptions): ZodSchemaType<string, ZodTypeDef, string>;
|
|
29
13
|
declare const sprintBuilder: {
|
|
@@ -42,7 +26,7 @@ export { proxyZ as z };
|
|
|
42
26
|
export { sprintBuilder as sprint };
|
|
43
27
|
export { fileValidators as files };
|
|
44
28
|
export { createFileSchema, createFilesArraySchema };
|
|
45
|
-
export type { FileSchemaType } from './types';
|
|
29
|
+
export type { FileSchemaType, SprintFiles } from './types';
|
|
46
30
|
export interface RouteSchemaOptions {
|
|
47
31
|
body?: ZodSchemaType<any, ZodTypeDef, any>;
|
|
48
32
|
queryParams?: ZodSchemaType<any, ZodTypeDef, any>;
|
|
@@ -57,6 +41,7 @@ export interface RouteSchemaOptions {
|
|
|
57
41
|
}
|
|
58
42
|
export declare function defineRouteSchema<T extends RouteSchemaOptions>(schema: T): RequestHandler & {
|
|
59
43
|
getFileFields?: () => string[];
|
|
44
|
+
hasStreamingFiles?: () => boolean;
|
|
60
45
|
};
|
|
61
|
-
export type { ZodSchema, ZodMiddlewareOptions } from './types';
|
|
46
|
+
export type { ZodSchema, ZodMiddlewareOptions, FileValidationOptions } from './types';
|
|
62
47
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/schemas/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/schemas/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,CAAC,EAAE,SAAS,IAAI,aAAa,EAAE,UAAU,EAAY,MAAM,KAAK,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAE5E,MAAM,MAAM,mBAAmB,GAAG,SAAS,MAAM,EAAE,GAAG,WAAW,MAAM,EAAE,CAAC;AAE1E,MAAM,WAAW,0BAA0B;IACvC,OAAO,CAAC,EAAE,mBAAmB,GAAG,mBAAmB,EAAE,CAAC;CACzD;AAYD,iBAAS,gBAAgB,CAAC,OAAO,GAAE,qBAA0B,EAAE,QAAQ,GAAE,OAAe,GAAG,cAAc,CAyFxG;AAED,iBAAS,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,GAAG,aAAa,CAAC,UAAU,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAK7I;AAED,QAAA,MAAM,cAAc,EAAE,cAcQ,CAAC;AAE/B,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,CAKvD;AAED,iBAAS,+BAA+B,CAAC,OAAO,CAAC,EAAE,0BAA0B,GAAG,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,CAKxH;AAED,QAAA,MAAM,aAAa;;CAElB,CAAC;AAEF,QAAA,MAAM,UAAU;;CAEf,CAAC;AAEF,KAAK,cAAc,GAAG,OAAO,UAAU,GAAG,CAAC,MAAM,OAAO,UAAU,CAAC,CAAC;AAQpE,KAAK,aAAa,GAAG,OAAO,CAAC,GAAG;IAC5B,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,OAAO,cAAc,CAAC;CAChC,CAAC;AAEF,QAAA,MAAM,MAAM,EAMN,aAAa,CAAC;AAEpB,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,CAAC;AACvB,OAAO,EAAE,aAAa,IAAI,MAAM,EAAE,CAAC;AACnC,OAAO,EAAE,cAAc,IAAI,KAAK,EAAE,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,CAAC;AAEpD,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3D,MAAM,WAAW,kBAAkB;IAC/B,IAAI,CAAC,EAAE,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;IAC3C,WAAW,CAAC,EAAE,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;IAClD,MAAM,CAAC,EAAE,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;IAC7C,OAAO,CAAC,EAAE,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;IAC9C,KAAK,CAAC,EAAE;QACJ,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;KAC5D,CAAC;IACF,MAAM,CAAC,EAAE;QACL,aAAa,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;KAC7D,CAAC;CACL;AAqBD,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,kBAAkB,EAAE,MAAM,EAAE,CAAC,GAAG,cAAc,GAAG;IACzF,aAAa,CAAC,EAAE,MAAM,MAAM,EAAE,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC;CACrC,CAgGA;AAED,YAAY,EAAE,SAAS,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
1
|
+
import { z, ZodType, ZodTypeDef } from 'zod';
|
|
2
2
|
export type ZodSchema = z.ZodType<any>;
|
|
3
3
|
export interface ZodMiddlewareOptions {
|
|
4
4
|
body?: ZodSchema;
|
|
@@ -16,6 +16,7 @@ export interface FileValidationOptions {
|
|
|
16
16
|
maxSize?: number;
|
|
17
17
|
minSize?: number;
|
|
18
18
|
required?: boolean;
|
|
19
|
+
_isStream?: boolean;
|
|
19
20
|
}
|
|
20
21
|
export type FileObject = {
|
|
21
22
|
fieldname: string;
|
|
@@ -24,11 +25,35 @@ export type FileObject = {
|
|
|
24
25
|
mimetype: string;
|
|
25
26
|
size: number;
|
|
26
27
|
buffer?: Buffer;
|
|
28
|
+
file?: NodeJS.ReadableStream;
|
|
27
29
|
};
|
|
28
|
-
export
|
|
30
|
+
export type StreamFileObject = {
|
|
31
|
+
fieldName: string;
|
|
32
|
+
file: NodeJS.ReadableStream;
|
|
33
|
+
filename: string;
|
|
34
|
+
encoding: string;
|
|
35
|
+
mimeType: string;
|
|
36
|
+
};
|
|
37
|
+
export type FileSchemaType = ZodType<FileObject, ZodTypeDef, FileObject> & {
|
|
29
38
|
format(ext: string | string[]): FileSchemaType;
|
|
30
39
|
mimeType(mimeType: string | string[]): FileSchemaType;
|
|
31
40
|
maxSize(maxSize: number): FileSchemaType;
|
|
32
41
|
minSize(minSize: number): FileSchemaType;
|
|
33
|
-
|
|
42
|
+
stream(): FileSchemaType;
|
|
43
|
+
image(): FileSchemaType;
|
|
44
|
+
document(): FileSchemaType;
|
|
45
|
+
video(): FileSchemaType;
|
|
46
|
+
audio(): FileSchemaType;
|
|
47
|
+
archive(): FileSchemaType;
|
|
48
|
+
any(): FileSchemaType;
|
|
49
|
+
_isStream?: boolean;
|
|
50
|
+
_extensions?: string[];
|
|
51
|
+
_mimeTypes?: string[];
|
|
52
|
+
_maxSize?: number;
|
|
53
|
+
_minSize?: number;
|
|
54
|
+
};
|
|
55
|
+
export type StreamFileSchemaType = FileSchemaType;
|
|
56
|
+
export type SprintFiles = {
|
|
57
|
+
[fieldname: string]: FileObject[];
|
|
58
|
+
};
|
|
34
59
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/modules/schemas/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/modules/schemas/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAE7C,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAEvC,MAAM,WAAW,oBAAoB;IACjC,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,MAAM,CAAC,EAAE;QACL,aAAa,CAAC,EAAE,SAAS,CAAC;KAC7B,CAAC;CACL;AAED,MAAM,WAAW,qBAAqB;IAClC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,MAAM,UAAU,GAAG;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC,cAAc,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,CAAC,GAAG;IACvE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,cAAc,CAAC;IAC/C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,cAAc,CAAC;IACtD,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAAC;IACzC,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAAC;IACzC,MAAM,IAAI,cAAc,CAAC;IACzB,KAAK,IAAI,cAAc,CAAC;IACxB,QAAQ,IAAI,cAAc,CAAC;IAC3B,KAAK,IAAI,cAAc,CAAC;IACxB,KAAK,IAAI,cAAc,CAAC;IACxB,OAAO,IAAI,cAAc,CAAC;IAC1B,GAAG,IAAI,cAAc,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC;AAElD,MAAM,MAAM,WAAW,GAAG;IACtB,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,EAAE,CAAC;CACrC,CAAC"}
|
package/dist/types/sprint.d.ts
CHANGED
|
@@ -58,15 +58,6 @@ export declare class Sprint {
|
|
|
58
58
|
files?: number;
|
|
59
59
|
};
|
|
60
60
|
headers?: Record<string, string>;
|
|
61
|
-
}): (req: Request, res: Response) =>
|
|
62
|
-
files: Array<{
|
|
63
|
-
fieldName: string;
|
|
64
|
-
file: NodeJS.ReadableStream;
|
|
65
|
-
filename: string;
|
|
66
|
-
encoding: string;
|
|
67
|
-
mimeType: string;
|
|
68
|
-
}>;
|
|
69
|
-
fields: Record<string, string>;
|
|
70
|
-
}>;
|
|
61
|
+
}): (req: Request, res: Response, next: (err?: any) => void) => void;
|
|
71
62
|
}
|
|
72
63
|
//# sourceMappingURL=sprint.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sprint.d.ts","sourceRoot":"","sources":["../../src/sprint.ts"],"names":[],"mappings":"AAYA,OAAO,OAAO,EAAE,EAAE,WAAW,EAA2C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC3G,OAAO,EAAE,OAAO,EAA+B,gBAAgB,EAAsC,MAAM,SAAS,CAAC;AAcrH,eAAO,MAAM,aAAa,SAAQ,CAAC;AACnC,eAAO,MAAM,YAAY,SAAS,CAAC;AA0CnC,qBAAa,MAAM;IACR,GAAG,EAAE,WAAW,CAAC;IACxB,OAAO,CAAC,IAAI,CAAwD;IACpE,OAAO,CAAC,UAAU,CAAsB;IACxC,OAAO,CAAC,eAAe,CAA2B;IAClD,OAAO,CAAC,YAAY,CAAwB;IAC5C,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,YAAY,CAAiB;IACrC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,iBAAiB,CAA4C;IACrE,OAAO,CAAC,QAAQ,CAA8C;IAC9D,OAAO,CAAC,OAAO,CAcT;IACN,OAAO,CAAC,OAAO,CAcT;IACN,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,gBAAgB,CAIhB;IACD,uBAAuB,EAAE,MAAM,CAAmB;IAClD,YAAY,EAAE,GAAG,CAAC;;YA6JX,IAAI;IAkDlB,OAAO,CAAC,YAAY;IAiDpB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA4B9B;;OAEG;YACW,eAAe;IAkC7B,OAAO,CAAC,eAAe;YAeT,UAAU;
|
|
1
|
+
{"version":3,"file":"sprint.d.ts","sourceRoot":"","sources":["../../src/sprint.ts"],"names":[],"mappings":"AAYA,OAAO,OAAO,EAAE,EAAE,WAAW,EAA2C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC3G,OAAO,EAAE,OAAO,EAA+B,gBAAgB,EAAsC,MAAM,SAAS,CAAC;AAcrH,eAAO,MAAM,aAAa,SAAQ,CAAC;AACnC,eAAO,MAAM,YAAY,SAAS,CAAC;AA0CnC,qBAAa,MAAM;IACR,GAAG,EAAE,WAAW,CAAC;IACxB,OAAO,CAAC,IAAI,CAAwD;IACpE,OAAO,CAAC,UAAU,CAAsB;IACxC,OAAO,CAAC,eAAe,CAA2B;IAClD,OAAO,CAAC,YAAY,CAAwB;IAC5C,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,YAAY,CAAiB;IACrC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,iBAAiB,CAA4C;IACrE,OAAO,CAAC,QAAQ,CAA8C;IAC9D,OAAO,CAAC,OAAO,CAcT;IACN,OAAO,CAAC,OAAO,CAcT;IACN,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,gBAAgB,CAIhB;IACD,uBAAuB,EAAE,MAAM,CAAmB;IAClD,YAAY,EAAE,GAAG,CAAC;;YA6JX,IAAI;IAkDlB,OAAO,CAAC,YAAY;IAiDpB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA4B9B;;OAEG;YACW,eAAe;IAkC7B,OAAO,CAAC,eAAe;YAeT,UAAU;YAsHV,YAAY;IAqB1B,OAAO,CAAC,YAAY;IAgCpB,+BAA+B;IAC/B,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,mBAAmB;IA+K3B,OAAO,CAAC,kBAAkB;IAqC1B,OAAO,CAAC,kBAAkB;IA8B1B,OAAO,CAAC,mBAAmB;IA+BpB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAClC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IACnC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAClC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IACrC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IACpC,GAAG,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,GAAG,gBAAgB,EAAE,YAAY,CAAC,EAAE,OAAO;IAY9E,gBAAgB,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI;IAInC,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,IAAI;IAgEnC,UAAU,CAAC,SAAS,GAAE,MAAe;IAIrC,WAAW,CAAC,UAAU,GAAE,MAAM,GAAG,MAAM,EAAY;IAKnD,YAAY,CAAC,OAAO,CAAC,EAAE;QAC1B,MAAM,CAAC,EAAE;YACL,QAAQ,CAAC,EAAE,MAAM,CAAC;YAClB,KAAK,CAAC,EAAE,MAAM,CAAC;SAClB,CAAC;QACF,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACpC,IACW,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,IAAI,KAAG,IAAI;CAsC5E"}
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Request, Response, NextFunction, RequestHandler } from 'express';
|
|
2
|
-
import { ZodSchema
|
|
2
|
+
import { ZodSchema } from './modules/schemas/types';
|
|
3
3
|
export type AsyncRequestHandler = (req: SprintRequest, res: SprintResponse, next: NextFunction) => Promise<any>;
|
|
4
4
|
export type Handler = (req: SprintRequest, res: SprintResponse, next: NextFunction) => any;
|
|
5
5
|
export type AuthorizationSource = `query:${string}` | `headers:${string}`;
|
|
@@ -9,10 +9,6 @@ export type SprintRequest = Request & {
|
|
|
9
9
|
authorization?: string;
|
|
10
10
|
};
|
|
11
11
|
custom: any;
|
|
12
|
-
file?: FileObject;
|
|
13
|
-
files?: {
|
|
14
|
-
[fieldname: string]: FileObject[];
|
|
15
|
-
} | FileObject[];
|
|
16
12
|
};
|
|
17
13
|
export type SprintResponse = Response;
|
|
18
14
|
declare global {
|
|
@@ -26,14 +22,6 @@ declare global {
|
|
|
26
22
|
}
|
|
27
23
|
}
|
|
28
24
|
}
|
|
29
|
-
declare module "express-serve-static-core" {
|
|
30
|
-
interface Request {
|
|
31
|
-
file?: FileObject;
|
|
32
|
-
files?: {
|
|
33
|
-
[fieldname: string]: FileObject[];
|
|
34
|
-
} | FileObject[];
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
25
|
export interface MiddlewareSchema {
|
|
38
26
|
body?: ZodSchema;
|
|
39
27
|
queryParams?: ZodSchema;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
|