sprint-es 0.0.155 → 0.0.157

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/cli.cjs CHANGED
@@ -387,31 +387,6 @@ async function runDoctor() {
387
387
  }
388
388
  logger.break();
389
389
  }
390
- const commandDependencies = {
391
- build: {
392
- ts: ["tsup", "typescript"]
393
- }
394
- };
395
- function checkDependencies(command2, isTS) {
396
- const config = commandDependencies[command2];
397
- if (!config) return [];
398
- const deps = config.ts ?? [];
399
- const missing = [];
400
- for (const dep of deps) {
401
- const binPath = path.join(projectRoot, "node_modules", ".bin", dep);
402
- if (!fs.existsSync(binPath)) missing.push(dep);
403
- }
404
- if (missing.length > 0) {
405
- console.error("\n❌ Missing required dependencies:");
406
- for (const dep of missing) {
407
- console.error(` • ${dep}`);
408
- }
409
- console.error("\n👉 Install with:");
410
- console.error(" npm install --save-dev " + missing.join(" "));
411
- console.error("");
412
- process.exit(1);
413
- }
414
- }
415
390
  async function main() {
416
391
  const hasDist = fs.existsSync(path.join(projectRoot, "dist"));
417
392
  const hasTsConfig = fs.existsSync(path.join(projectRoot, "tsconfig.json"));
@@ -432,7 +407,6 @@ async function main() {
432
407
  }
433
408
  case "build": {
434
409
  console.log("🚀 Building for production...");
435
- checkDependencies("build");
436
410
  const distPath = path.join(projectRoot, "dist");
437
411
  const tsconfigPath = path.join(projectRoot, "tsconfig.json");
438
412
  const hasSprintConfigTs = fs.existsSync(path.join(projectRoot, "sprint.config.ts"));
@@ -29,6 +29,8 @@ const cors = require("cors");
29
29
  const path = require("path");
30
30
  const morgan = require("morgan");
31
31
  const dotenv = require("dotenv");
32
+ const multer = require("multer");
33
+ const busboy = require("busboy");
32
34
  const url = require("url");
33
35
  const rateLimit = require("toolkitify/rate-limit");
34
36
  const modules_schemas_index = require("./modules/schemas/index.cjs");
@@ -85,10 +87,7 @@ const isProduction = isProd;
85
87
  function isEnabledInEnv(value) {
86
88
  if (value === void 0) return false;
87
89
  if (typeof value === "boolean") return value;
88
- if (Array.isArray(value)) {
89
- const env = nodeEnv || "development";
90
- return value.includes(env);
91
- }
90
+ if (Array.isArray(value)) return value.includes(nodeEnv || "development");
92
91
  return false;
93
92
  }
94
93
  async function findProjectRoot(startDir) {
@@ -146,6 +145,7 @@ class Sprint {
146
145
  };
147
146
  this.graphqlSchema = null;
148
147
  this.registeredRoutes = [];
148
+ this.fileMemoryUploadedLimit = 5 * 1024 * 1024;
149
149
  this.app = express();
150
150
  loadSprintConfig().then((config) => {
151
151
  const defaults = {
@@ -194,6 +194,7 @@ class Sprint {
194
194
  path: finalConfig.graphql?.graphiql?.path || "/graphiql"
195
195
  }
196
196
  };
197
+ this.fileMemoryUploadedLimit = finalConfig.fileMemoryUploadedLimit || 5 * 1024 * 1024;
197
198
  const openApiPath = this.openapi.path;
198
199
  const swaggerPath = this.openapi.swaggerUi.path;
199
200
  const graphqlPath = this.graphql.path;
@@ -219,6 +220,10 @@ class Sprint {
219
220
  this.loadDefaults();
220
221
  this.loadHealthcheck();
221
222
  this.routesLoaded = this.init();
223
+ this.memoryUpload = multer({
224
+ storage: multer.memoryStorage(),
225
+ limits: { fileSize: this.fileMemoryUploadedLimit }
226
+ });
222
227
  this.routesLoaded.then(async () => {
223
228
  if (this.openapi.generateOnBuild) {
224
229
  this.app.get(this.openapi.path, (_, res) => {
@@ -350,7 +355,7 @@ class Sprint {
350
355
  this.app.use(express.urlencoded({ limit: this.urlEncodedLimit, extended: false }));
351
356
  }
352
357
  /**
353
- * Gets all matching middlewares for a given route path, sorted by priority
358
+ * Gets all matching middlewares for a given route path, sorted by priority.
354
359
  */
355
360
  getMiddlewaresForRoute(routePath) {
356
361
  const matched = [];
@@ -374,7 +379,7 @@ class Sprint {
374
379
  return matched.map((m) => m.handler);
375
380
  }
376
381
  /**
377
- * Load all middleware files from the middlewares folder
382
+ * Load all middleware files from the middlewares folder.
378
383
  */
379
384
  async loadMiddlewares(middlewaresPath) {
380
385
  const fileExtensions = isProd ? [".mjs", ".js"] : [".ts"];
@@ -459,11 +464,37 @@ class Sprint {
459
464
  }
460
465
  }
461
466
  const routeMiddlewares = this.getMiddlewaresForRoute(routePath);
467
+ let fileUploadMiddleware = null;
468
+ for (const layer of router.stack) {
469
+ if (!layer.route) continue;
470
+ for (const routeLayer of layer.route.stack) {
471
+ const handler = routeLayer.handle;
472
+ const handlerSchema = handler.__sprintRouteSchema;
473
+ if (handlerSchema?.files && typeof handlerSchema.files === "object" && "field" in handlerSchema.files) {
474
+ const fileConfig = handlerSchema.files;
475
+ if (fileConfig.maxCount) {
476
+ fileUploadMiddleware = this.uploadFiles(fileConfig.field);
477
+ } else {
478
+ fileUploadMiddleware = this.uploadFile(fileConfig.field);
479
+ }
480
+ break;
481
+ }
482
+ }
483
+ if (fileUploadMiddleware) break;
484
+ }
462
485
  if (routeMiddlewares.length > 0) {
463
- this.app.use(finalRoute, ...routeMiddlewares, router);
486
+ if (fileUploadMiddleware) {
487
+ this.app.use(finalRoute, fileUploadMiddleware, ...routeMiddlewares, router);
488
+ } else {
489
+ this.app.use(finalRoute, ...routeMiddlewares, router);
490
+ }
464
491
  if (isVerbose) console.log(`[Sprint] Loaded route: ${finalRoute} -> ${filePath} (with ${routeMiddlewares.length} middleware(s))`);
465
492
  } else {
466
- this.app.use(finalRoute, router);
493
+ if (fileUploadMiddleware) {
494
+ this.app.use(finalRoute, fileUploadMiddleware, router);
495
+ } else {
496
+ this.app.use(finalRoute, router);
497
+ }
467
498
  if (isVerbose) console.log(`[Sprint] Loaded route: ${finalRoute} -> ${filePath}`);
468
499
  }
469
500
  this.counters.routes += router.stack.length;
@@ -828,6 +859,44 @@ class Sprint {
828
859
  tryListen(basePort);
829
860
  if (callback) callback();
830
861
  }
862
+ uploadFile(fieldName = "file") {
863
+ return this.memoryUpload.single(fieldName);
864
+ }
865
+ uploadFiles(fieldNames = "files") {
866
+ if (Array.isArray(fieldNames)) return this.memoryUpload.fields(fieldNames.map((name) => ({ name })));
867
+ return this.memoryUpload.array(fieldNames);
868
+ }
869
+ streamUpload(options) {
870
+ return (req, res) => {
871
+ return new Promise((resolve, reject) => {
872
+ const bb = busboy({
873
+ headers: req.headers,
874
+ limits: options?.limits
875
+ });
876
+ const files = [];
877
+ const fields = {};
878
+ bb.on("file", (fieldName, file, info) => {
879
+ files.push({
880
+ fieldName,
881
+ file,
882
+ filename: info.filename,
883
+ encoding: info.encoding,
884
+ mimeType: info.mimeType
885
+ });
886
+ });
887
+ bb.on("field", (fieldName, val) => {
888
+ fields[fieldName] = val;
889
+ });
890
+ bb.on("finish", () => {
891
+ resolve({ files, fields });
892
+ });
893
+ bb.on("error", (err) => {
894
+ reject(err);
895
+ });
896
+ req.pipe(bb);
897
+ });
898
+ };
899
+ }
831
900
  }
832
901
  function createSchemaValidationMiddleware(schema) {
833
902
  const headersSchema = schema.headers ? modules_schemas_index.normalizeHeadersSchema(schema.headers) : null;
@@ -1,6 +1,110 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const zod = require("zod");
4
+ function normalizeExtensions(ext) {
5
+ if (!ext) return [];
6
+ return (Array.isArray(ext) ? ext : [ext]).map((e) => e.toLowerCase().startsWith(".") ? e.toLowerCase() : `.${e.toLowerCase()}`);
7
+ }
8
+ function normalizeMimeTypes(mime) {
9
+ if (!mime) return [];
10
+ return (Array.isArray(mime) ? mime : [mime]).map((m) => m.toLowerCase());
11
+ }
12
+ function createFileSchema(options = {}) {
13
+ const extensions = normalizeExtensions(options.ext);
14
+ const mimeTypes = normalizeMimeTypes(options.mimeType);
15
+ const fileSchema = zod.z.object({
16
+ fieldname: zod.z.string(),
17
+ originalname: zod.z.string(),
18
+ encoding: zod.z.string(),
19
+ mimetype: zod.z.string(),
20
+ size: zod.z.number(),
21
+ buffer: zod.z.instanceof(Buffer).optional()
22
+ });
23
+ return fileSchema.refine((file) => {
24
+ if (extensions.length === 0) return true;
25
+ const fileExt = file.originalname.toLowerCase().substring(file.originalname.lastIndexOf("."));
26
+ return extensions.includes(fileExt);
27
+ }, {
28
+ message: `Invalid file extension. Allowed: ${extensions.join(", ")}`,
29
+ path: ["originalname"]
30
+ }).refine((file) => {
31
+ if (mimeTypes.length === 0) return true;
32
+ return mimeTypes.includes(file.mimetype.toLowerCase());
33
+ }, {
34
+ message: `Invalid mime type. Allowed: ${mimeTypes.join(", ")}`,
35
+ path: ["mimetype"]
36
+ }).refine((file) => {
37
+ if (options.maxSize === void 0) return true;
38
+ return file.size <= options.maxSize;
39
+ }, {
40
+ message: `File size exceeds maximum of ${options.maxSize} bytes`,
41
+ path: ["size"]
42
+ }).refine((file) => {
43
+ if (options.minSize === void 0) return true;
44
+ return file.size >= options.minSize;
45
+ }, {
46
+ message: `File size must be at least ${options.minSize} bytes`,
47
+ path: ["size"]
48
+ });
49
+ }
50
+ function createFilesArraySchema(fieldName, options = {}) {
51
+ const fileSchema = createFileSchema({ ...options });
52
+ return zod.z.array(fileSchema).min(options.required === false ? 0 : 1, {
53
+ message: options.required === false ? void 0 : `At least one file is required for field "${fieldName}"`
54
+ });
55
+ }
56
+ const fileValidators = {
57
+ ext: (ext) => {
58
+ const extensions = normalizeExtensions(ext);
59
+ return createFileSchema({ ext: extensions });
60
+ },
61
+ mimeType: (mimeType) => {
62
+ const mimeTypes = normalizeMimeTypes(mimeType);
63
+ return createFileSchema({ mimeType: mimeTypes });
64
+ },
65
+ maxSize: (maxSize) => {
66
+ return createFileSchema({ maxSize });
67
+ },
68
+ minSize: (minSize) => {
69
+ return createFileSchema({ minSize });
70
+ },
71
+ image: () => {
72
+ return createFileSchema({
73
+ mimeType: ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml"],
74
+ ext: ["jpg", "jpeg", "png", "gif", "webp", "svg"]
75
+ });
76
+ },
77
+ document: () => {
78
+ return createFileSchema({
79
+ mimeType: ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "text/plain"],
80
+ ext: ["pdf", "doc", "docx", "txt"]
81
+ });
82
+ },
83
+ video: () => {
84
+ return createFileSchema({
85
+ mimeType: ["video/mp4", "video/webm", "video/ogg"],
86
+ ext: ["mp4", "webm", "ogg"]
87
+ });
88
+ },
89
+ audio: () => {
90
+ return createFileSchema({
91
+ mimeType: ["audio/mpeg", "audio/wav", "audio/ogg", "audio/webm"],
92
+ ext: ["mp3", "wav", "ogg", "webm"]
93
+ });
94
+ },
95
+ archive: () => {
96
+ return createFileSchema({
97
+ mimeType: ["application/zip", "application/x-rar-compressed", "application/x-7z-compressed"],
98
+ ext: ["zip", "rar", "7z"]
99
+ });
100
+ },
101
+ any: () => {
102
+ return createFileSchema({});
103
+ },
104
+ field: (fieldName, options) => {
105
+ return createFilesArraySchema(fieldName, options);
106
+ }
107
+ };
4
108
  function normalizeHeadersSchema(schema) {
5
109
  const shape = schema.shape ?? schema._def?.shape?.();
6
110
  if (!shape) return schema;
@@ -25,6 +129,7 @@ Object.assign(sprintCallable, sprintAuth);
25
129
  const proxyZ = new Proxy(zod.z, {
26
130
  get(target, prop) {
27
131
  if (prop === "sprint") return sprintCallable;
132
+ if (prop === "files") return fileValidators;
28
133
  return target[prop];
29
134
  }
30
135
  });
@@ -43,6 +148,7 @@ function parseSchema(schema, data) {
43
148
  }
44
149
  function defineRouteSchema(schema) {
45
150
  const headersSchema = schema.headers ? normalizeHeadersSchema(schema.headers) : null;
151
+ const fileConfig = typeof schema.files === "object" && "field" in schema.files ? schema.files : null;
46
152
  const middleware = (req, res, next) => {
47
153
  const errors = [];
48
154
  const method = req.method.toUpperCase();
@@ -64,6 +170,24 @@ function defineRouteSchema(schema) {
64
170
  const result = headersSchema.safeParse(normalizedHeaders);
65
171
  if (!result.success) errors.push(...result.errors.map((e) => ({ location: "headers", ...e })));
66
172
  }
173
+ let filesData = [];
174
+ if (schema.files) {
175
+ if (fileConfig) {
176
+ const fieldFiles = req.file ? [req.file] : [];
177
+ const multiFiles = req.files?.[fileConfig.field] || [];
178
+ filesData = [...fieldFiles, ...Array.isArray(multiFiles) ? multiFiles : []];
179
+ if (fileConfig.maxCount && filesData.length > fileConfig.maxCount) errors.push({ location: "files", path: fileConfig.field, message: `Maximum ${fileConfig.maxCount} files allowed` });
180
+ if (fileConfig.schema && filesData.length > 0) {
181
+ const result = parseSchema(fileConfig.schema, filesData);
182
+ if (!result.success) errors.push(...result.errors.map((e) => ({ location: "files", ...e })));
183
+ }
184
+ } else {
185
+ const filesSchema = schema.files;
186
+ const reqFiles = req.files || (req.file ? [req.file] : []);
187
+ const result = parseSchema(filesSchema, reqFiles);
188
+ if (!result.success) errors.push(...result.errors.map((e) => ({ location: "files", ...e })));
189
+ }
190
+ }
67
191
  if (schema.sprint?.authorization) {
68
192
  const authSchema = schema.sprint.authorization;
69
193
  const description = authSchema._def?.description;
@@ -71,9 +195,7 @@ function defineRouteSchema(schema) {
71
195
  if (description) {
72
196
  try {
73
197
  const parsed = JSON.parse(description);
74
- if (parsed.__sprintAuthorization && parsed.sources) {
75
- sources = Array.isArray(parsed.sources) ? parsed.sources : [parsed.sources];
76
- }
198
+ if (parsed.__sprintAuthorization && parsed.sources) sources = Array.isArray(parsed.sources) ? parsed.sources : [parsed.sources];
77
199
  } catch {
78
200
  }
79
201
  }
@@ -105,9 +227,18 @@ function defineRouteSchema(schema) {
105
227
  next();
106
228
  };
107
229
  middleware.__sprintRouteSchema = schema;
230
+ if (fileConfig) {
231
+ middleware.applyFileUpload = function(sprint) {
232
+ if (fileConfig.maxCount) return sprint.uploadFiles(fileConfig.field);
233
+ return sprint.uploadFile(fileConfig.field);
234
+ };
235
+ }
108
236
  return middleware;
109
237
  }
238
+ exports.createFileSchema = createFileSchema;
239
+ exports.createFilesArraySchema = createFilesArraySchema;
110
240
  exports.defineRouteSchema = defineRouteSchema;
241
+ exports.files = fileValidators;
111
242
  exports.normalizeHeadersSchema = normalizeHeadersSchema;
112
243
  exports.sprint = sprintBuilder;
113
244
  exports.z = proxyZ;
package/dist/esm/cli.js CHANGED
@@ -368,31 +368,6 @@ async function runDoctor() {
368
368
  }
369
369
  logger.break();
370
370
  }
371
- const commandDependencies = {
372
- build: {
373
- ts: ["tsup", "typescript"]
374
- }
375
- };
376
- function checkDependencies(command2, isTS) {
377
- const config = commandDependencies[command2];
378
- if (!config) return [];
379
- const deps = config.ts ?? [];
380
- const missing = [];
381
- for (const dep of deps) {
382
- const binPath = join(projectRoot, "node_modules", ".bin", dep);
383
- if (!existsSync(binPath)) missing.push(dep);
384
- }
385
- if (missing.length > 0) {
386
- console.error("\n❌ Missing required dependencies:");
387
- for (const dep of missing) {
388
- console.error(` • ${dep}`);
389
- }
390
- console.error("\n👉 Install with:");
391
- console.error(" npm install --save-dev " + missing.join(" "));
392
- console.error("");
393
- process.exit(1);
394
- }
395
- }
396
371
  async function main() {
397
372
  const hasDist = existsSync(join(projectRoot, "dist"));
398
373
  const hasTsConfig = existsSync(join(projectRoot, "tsconfig.json"));
@@ -413,7 +388,6 @@ async function main() {
413
388
  }
414
389
  case "build": {
415
390
  console.log("🚀 Building for production...");
416
- checkDependencies("build");
417
391
  const distPath = join(projectRoot, "dist");
418
392
  const tsconfigPath = join(projectRoot, "tsconfig.json");
419
393
  const hasSprintConfigTs = existsSync(join(projectRoot, "sprint.config.ts"));
package/dist/esm/index.js CHANGED
@@ -5,6 +5,8 @@ import cors from "cors";
5
5
  import path from "path";
6
6
  import morgan from "morgan";
7
7
  import dotenv from "dotenv";
8
+ import multer from "multer";
9
+ import busboy from "busboy";
8
10
  import { pathToFileURL } from "url";
9
11
  import { RateLimiter } from "toolkitify/rate-limit";
10
12
  import { normalizeHeadersSchema } from "./modules/schemas/index.js";
@@ -60,10 +62,7 @@ const isProduction = isProd;
60
62
  function isEnabledInEnv(value) {
61
63
  if (value === void 0) return false;
62
64
  if (typeof value === "boolean") return value;
63
- if (Array.isArray(value)) {
64
- const env = nodeEnv || "development";
65
- return value.includes(env);
66
- }
65
+ if (Array.isArray(value)) return value.includes(nodeEnv || "development");
67
66
  return false;
68
67
  }
69
68
  async function findProjectRoot(startDir) {
@@ -121,6 +120,7 @@ class Sprint {
121
120
  };
122
121
  this.graphqlSchema = null;
123
122
  this.registeredRoutes = [];
123
+ this.fileMemoryUploadedLimit = 5 * 1024 * 1024;
124
124
  this.app = express();
125
125
  loadSprintConfig().then((config) => {
126
126
  const defaults = {
@@ -169,6 +169,7 @@ class Sprint {
169
169
  path: finalConfig.graphql?.graphiql?.path || "/graphiql"
170
170
  }
171
171
  };
172
+ this.fileMemoryUploadedLimit = finalConfig.fileMemoryUploadedLimit || 5 * 1024 * 1024;
172
173
  const openApiPath = this.openapi.path;
173
174
  const swaggerPath = this.openapi.swaggerUi.path;
174
175
  const graphqlPath = this.graphql.path;
@@ -194,6 +195,10 @@ class Sprint {
194
195
  this.loadDefaults();
195
196
  this.loadHealthcheck();
196
197
  this.routesLoaded = this.init();
198
+ this.memoryUpload = multer({
199
+ storage: multer.memoryStorage(),
200
+ limits: { fileSize: this.fileMemoryUploadedLimit }
201
+ });
197
202
  this.routesLoaded.then(async () => {
198
203
  if (this.openapi.generateOnBuild) {
199
204
  this.app.get(this.openapi.path, (_, res) => {
@@ -325,7 +330,7 @@ class Sprint {
325
330
  this.app.use(express.urlencoded({ limit: this.urlEncodedLimit, extended: false }));
326
331
  }
327
332
  /**
328
- * Gets all matching middlewares for a given route path, sorted by priority
333
+ * Gets all matching middlewares for a given route path, sorted by priority.
329
334
  */
330
335
  getMiddlewaresForRoute(routePath) {
331
336
  const matched = [];
@@ -349,7 +354,7 @@ class Sprint {
349
354
  return matched.map((m) => m.handler);
350
355
  }
351
356
  /**
352
- * Load all middleware files from the middlewares folder
357
+ * Load all middleware files from the middlewares folder.
353
358
  */
354
359
  async loadMiddlewares(middlewaresPath) {
355
360
  const fileExtensions = isProd ? [".mjs", ".js"] : [".ts"];
@@ -434,11 +439,37 @@ class Sprint {
434
439
  }
435
440
  }
436
441
  const routeMiddlewares = this.getMiddlewaresForRoute(routePath);
442
+ let fileUploadMiddleware = null;
443
+ for (const layer of router.stack) {
444
+ if (!layer.route) continue;
445
+ for (const routeLayer of layer.route.stack) {
446
+ const handler = routeLayer.handle;
447
+ const handlerSchema = handler.__sprintRouteSchema;
448
+ if (handlerSchema?.files && typeof handlerSchema.files === "object" && "field" in handlerSchema.files) {
449
+ const fileConfig = handlerSchema.files;
450
+ if (fileConfig.maxCount) {
451
+ fileUploadMiddleware = this.uploadFiles(fileConfig.field);
452
+ } else {
453
+ fileUploadMiddleware = this.uploadFile(fileConfig.field);
454
+ }
455
+ break;
456
+ }
457
+ }
458
+ if (fileUploadMiddleware) break;
459
+ }
437
460
  if (routeMiddlewares.length > 0) {
438
- this.app.use(finalRoute, ...routeMiddlewares, router);
461
+ if (fileUploadMiddleware) {
462
+ this.app.use(finalRoute, fileUploadMiddleware, ...routeMiddlewares, router);
463
+ } else {
464
+ this.app.use(finalRoute, ...routeMiddlewares, router);
465
+ }
439
466
  if (isVerbose) console.log(`[Sprint] Loaded route: ${finalRoute} -> ${filePath} (with ${routeMiddlewares.length} middleware(s))`);
440
467
  } else {
441
- this.app.use(finalRoute, router);
468
+ if (fileUploadMiddleware) {
469
+ this.app.use(finalRoute, fileUploadMiddleware, router);
470
+ } else {
471
+ this.app.use(finalRoute, router);
472
+ }
442
473
  if (isVerbose) console.log(`[Sprint] Loaded route: ${finalRoute} -> ${filePath}`);
443
474
  }
444
475
  this.counters.routes += router.stack.length;
@@ -803,6 +834,44 @@ class Sprint {
803
834
  tryListen(basePort);
804
835
  if (callback) callback();
805
836
  }
837
+ uploadFile(fieldName = "file") {
838
+ return this.memoryUpload.single(fieldName);
839
+ }
840
+ uploadFiles(fieldNames = "files") {
841
+ if (Array.isArray(fieldNames)) return this.memoryUpload.fields(fieldNames.map((name) => ({ name })));
842
+ return this.memoryUpload.array(fieldNames);
843
+ }
844
+ streamUpload(options) {
845
+ return (req, res) => {
846
+ return new Promise((resolve, reject) => {
847
+ const bb = busboy({
848
+ headers: req.headers,
849
+ limits: options?.limits
850
+ });
851
+ const files = [];
852
+ const fields = {};
853
+ bb.on("file", (fieldName, file, info) => {
854
+ files.push({
855
+ fieldName,
856
+ file,
857
+ filename: info.filename,
858
+ encoding: info.encoding,
859
+ mimeType: info.mimeType
860
+ });
861
+ });
862
+ bb.on("field", (fieldName, val) => {
863
+ fields[fieldName] = val;
864
+ });
865
+ bb.on("finish", () => {
866
+ resolve({ files, fields });
867
+ });
868
+ bb.on("error", (err) => {
869
+ reject(err);
870
+ });
871
+ req.pipe(bb);
872
+ });
873
+ };
874
+ }
806
875
  }
807
876
  function createSchemaValidationMiddleware(schema) {
808
877
  const headersSchema = schema.headers ? normalizeHeadersSchema(schema.headers) : null;
@@ -1,4 +1,108 @@
1
1
  import { z } from "zod";
2
+ function normalizeExtensions(ext) {
3
+ if (!ext) return [];
4
+ return (Array.isArray(ext) ? ext : [ext]).map((e) => e.toLowerCase().startsWith(".") ? e.toLowerCase() : `.${e.toLowerCase()}`);
5
+ }
6
+ function normalizeMimeTypes(mime) {
7
+ if (!mime) return [];
8
+ return (Array.isArray(mime) ? mime : [mime]).map((m) => m.toLowerCase());
9
+ }
10
+ function createFileSchema(options = {}) {
11
+ const extensions = normalizeExtensions(options.ext);
12
+ const mimeTypes = normalizeMimeTypes(options.mimeType);
13
+ const fileSchema = z.object({
14
+ fieldname: z.string(),
15
+ originalname: z.string(),
16
+ encoding: z.string(),
17
+ mimetype: z.string(),
18
+ size: z.number(),
19
+ buffer: z.instanceof(Buffer).optional()
20
+ });
21
+ return fileSchema.refine((file) => {
22
+ if (extensions.length === 0) return true;
23
+ const fileExt = file.originalname.toLowerCase().substring(file.originalname.lastIndexOf("."));
24
+ return extensions.includes(fileExt);
25
+ }, {
26
+ message: `Invalid file extension. Allowed: ${extensions.join(", ")}`,
27
+ path: ["originalname"]
28
+ }).refine((file) => {
29
+ if (mimeTypes.length === 0) return true;
30
+ return mimeTypes.includes(file.mimetype.toLowerCase());
31
+ }, {
32
+ message: `Invalid mime type. Allowed: ${mimeTypes.join(", ")}`,
33
+ path: ["mimetype"]
34
+ }).refine((file) => {
35
+ if (options.maxSize === void 0) return true;
36
+ return file.size <= options.maxSize;
37
+ }, {
38
+ message: `File size exceeds maximum of ${options.maxSize} bytes`,
39
+ path: ["size"]
40
+ }).refine((file) => {
41
+ if (options.minSize === void 0) return true;
42
+ return file.size >= options.minSize;
43
+ }, {
44
+ message: `File size must be at least ${options.minSize} bytes`,
45
+ path: ["size"]
46
+ });
47
+ }
48
+ function createFilesArraySchema(fieldName, options = {}) {
49
+ const fileSchema = createFileSchema({ ...options });
50
+ return z.array(fileSchema).min(options.required === false ? 0 : 1, {
51
+ message: options.required === false ? void 0 : `At least one file is required for field "${fieldName}"`
52
+ });
53
+ }
54
+ const fileValidators = {
55
+ ext: (ext) => {
56
+ const extensions = normalizeExtensions(ext);
57
+ return createFileSchema({ ext: extensions });
58
+ },
59
+ mimeType: (mimeType) => {
60
+ const mimeTypes = normalizeMimeTypes(mimeType);
61
+ return createFileSchema({ mimeType: mimeTypes });
62
+ },
63
+ maxSize: (maxSize) => {
64
+ return createFileSchema({ maxSize });
65
+ },
66
+ minSize: (minSize) => {
67
+ return createFileSchema({ minSize });
68
+ },
69
+ image: () => {
70
+ return createFileSchema({
71
+ mimeType: ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml"],
72
+ ext: ["jpg", "jpeg", "png", "gif", "webp", "svg"]
73
+ });
74
+ },
75
+ document: () => {
76
+ return createFileSchema({
77
+ mimeType: ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "text/plain"],
78
+ ext: ["pdf", "doc", "docx", "txt"]
79
+ });
80
+ },
81
+ video: () => {
82
+ return createFileSchema({
83
+ mimeType: ["video/mp4", "video/webm", "video/ogg"],
84
+ ext: ["mp4", "webm", "ogg"]
85
+ });
86
+ },
87
+ audio: () => {
88
+ return createFileSchema({
89
+ mimeType: ["audio/mpeg", "audio/wav", "audio/ogg", "audio/webm"],
90
+ ext: ["mp3", "wav", "ogg", "webm"]
91
+ });
92
+ },
93
+ archive: () => {
94
+ return createFileSchema({
95
+ mimeType: ["application/zip", "application/x-rar-compressed", "application/x-7z-compressed"],
96
+ ext: ["zip", "rar", "7z"]
97
+ });
98
+ },
99
+ any: () => {
100
+ return createFileSchema({});
101
+ },
102
+ field: (fieldName, options) => {
103
+ return createFilesArraySchema(fieldName, options);
104
+ }
105
+ };
2
106
  function normalizeHeadersSchema(schema) {
3
107
  const shape = schema.shape ?? schema._def?.shape?.();
4
108
  if (!shape) return schema;
@@ -23,6 +127,7 @@ Object.assign(sprintCallable, sprintAuth);
23
127
  const proxyZ = new Proxy(z, {
24
128
  get(target, prop) {
25
129
  if (prop === "sprint") return sprintCallable;
130
+ if (prop === "files") return fileValidators;
26
131
  return target[prop];
27
132
  }
28
133
  });
@@ -41,6 +146,7 @@ function parseSchema(schema, data) {
41
146
  }
42
147
  function defineRouteSchema(schema) {
43
148
  const headersSchema = schema.headers ? normalizeHeadersSchema(schema.headers) : null;
149
+ const fileConfig = typeof schema.files === "object" && "field" in schema.files ? schema.files : null;
44
150
  const middleware = (req, res, next) => {
45
151
  const errors = [];
46
152
  const method = req.method.toUpperCase();
@@ -62,6 +168,24 @@ function defineRouteSchema(schema) {
62
168
  const result = headersSchema.safeParse(normalizedHeaders);
63
169
  if (!result.success) errors.push(...result.errors.map((e) => ({ location: "headers", ...e })));
64
170
  }
171
+ let filesData = [];
172
+ if (schema.files) {
173
+ if (fileConfig) {
174
+ const fieldFiles = req.file ? [req.file] : [];
175
+ const multiFiles = req.files?.[fileConfig.field] || [];
176
+ filesData = [...fieldFiles, ...Array.isArray(multiFiles) ? multiFiles : []];
177
+ if (fileConfig.maxCount && filesData.length > fileConfig.maxCount) errors.push({ location: "files", path: fileConfig.field, message: `Maximum ${fileConfig.maxCount} files allowed` });
178
+ if (fileConfig.schema && filesData.length > 0) {
179
+ const result = parseSchema(fileConfig.schema, filesData);
180
+ if (!result.success) errors.push(...result.errors.map((e) => ({ location: "files", ...e })));
181
+ }
182
+ } else {
183
+ const filesSchema = schema.files;
184
+ const reqFiles = req.files || (req.file ? [req.file] : []);
185
+ const result = parseSchema(filesSchema, reqFiles);
186
+ if (!result.success) errors.push(...result.errors.map((e) => ({ location: "files", ...e })));
187
+ }
188
+ }
65
189
  if (schema.sprint?.authorization) {
66
190
  const authSchema = schema.sprint.authorization;
67
191
  const description = authSchema._def?.description;
@@ -69,9 +193,7 @@ function defineRouteSchema(schema) {
69
193
  if (description) {
70
194
  try {
71
195
  const parsed = JSON.parse(description);
72
- if (parsed.__sprintAuthorization && parsed.sources) {
73
- sources = Array.isArray(parsed.sources) ? parsed.sources : [parsed.sources];
74
- }
196
+ if (parsed.__sprintAuthorization && parsed.sources) sources = Array.isArray(parsed.sources) ? parsed.sources : [parsed.sources];
75
197
  } catch {
76
198
  }
77
199
  }
@@ -103,10 +225,19 @@ function defineRouteSchema(schema) {
103
225
  next();
104
226
  };
105
227
  middleware.__sprintRouteSchema = schema;
228
+ if (fileConfig) {
229
+ middleware.applyFileUpload = function(sprint) {
230
+ if (fileConfig.maxCount) return sprint.uploadFiles(fileConfig.field);
231
+ return sprint.uploadFile(fileConfig.field);
232
+ };
233
+ }
106
234
  return middleware;
107
235
  }
108
236
  export {
237
+ createFileSchema,
238
+ createFilesArraySchema,
109
239
  defineRouteSchema,
240
+ fileValidators as files,
110
241
  normalizeHeadersSchema,
111
242
  sprintBuilder as sprint,
112
243
  proxyZ as z
@@ -1,9 +1,32 @@
1
1
  import { RequestHandler } from 'express';
2
2
  import { z, ZodSchema as ZodSchemaType, ZodTypeDef } from 'zod';
3
+ import { FileObject } from './types';
3
4
  export type AuthorizationSource = `query:${string}` | `headers:${string}`;
4
5
  export interface SprintAuthorizationOptions {
5
6
  sources?: AuthorizationSource | AuthorizationSource[];
6
7
  }
8
+ export interface FileValidationOptions {
9
+ ext?: string | string[];
10
+ mimeType?: string | string[];
11
+ maxSize?: number;
12
+ minSize?: number;
13
+ required?: boolean;
14
+ }
15
+ declare function createFileSchema(options?: FileValidationOptions): ZodSchemaType<FileObject, ZodTypeDef, FileObject>;
16
+ declare function createFilesArraySchema(fieldName: string, options?: FileValidationOptions): ZodSchemaType<FileObject[], ZodTypeDef, FileObject[]>;
17
+ declare const fileValidators: {
18
+ ext: (ext: string | string[]) => z.ZodType<FileObject, z.ZodTypeDef, FileObject>;
19
+ mimeType: (mimeType: string | string[]) => z.ZodType<FileObject, z.ZodTypeDef, FileObject>;
20
+ maxSize: (maxSize: number) => z.ZodType<FileObject, z.ZodTypeDef, FileObject>;
21
+ minSize: (minSize: number) => z.ZodType<FileObject, z.ZodTypeDef, FileObject>;
22
+ image: () => z.ZodType<FileObject, z.ZodTypeDef, FileObject>;
23
+ document: () => z.ZodType<FileObject, z.ZodTypeDef, FileObject>;
24
+ video: () => z.ZodType<FileObject, z.ZodTypeDef, FileObject>;
25
+ audio: () => z.ZodType<FileObject, z.ZodTypeDef, FileObject>;
26
+ archive: () => z.ZodType<FileObject, z.ZodTypeDef, FileObject>;
27
+ any: () => z.ZodType<FileObject, z.ZodTypeDef, FileObject>;
28
+ field: (fieldName: string, options?: FileValidationOptions) => z.ZodType<FileObject[], z.ZodTypeDef, FileObject[]>;
29
+ };
7
30
  export declare function normalizeHeadersSchema(schema: any): any;
8
31
  declare function createSprintAuthorizationSchema(options?: SprintAuthorizationOptions): ZodSchemaType<string, ZodTypeDef, string>;
9
32
  declare const sprintBuilder: {
@@ -15,19 +38,29 @@ declare const sprintAuth: {
15
38
  type SprintCallable = typeof sprintAuth & (() => typeof sprintAuth);
16
39
  type ZodWithSprint = typeof z & {
17
40
  sprint: SprintCallable;
41
+ files: typeof fileValidators;
18
42
  };
19
43
  declare const proxyZ: ZodWithSprint;
20
44
  export { proxyZ as z };
21
45
  export { sprintBuilder as sprint };
46
+ export { fileValidators as files };
47
+ export { createFileSchema, createFilesArraySchema };
22
48
  export interface RouteSchemaOptions {
23
49
  body?: ZodSchemaType<any, ZodTypeDef, any>;
24
50
  queryParams?: ZodSchemaType<any, ZodTypeDef, any>;
25
51
  params?: ZodSchemaType<any, ZodTypeDef, any>;
26
52
  headers?: ZodSchemaType<any, ZodTypeDef, any>;
53
+ files?: ZodSchemaType<any, ZodTypeDef, any> | {
54
+ field: string;
55
+ maxCount?: number;
56
+ schema?: ZodSchemaType<any, ZodTypeDef, any>;
57
+ };
27
58
  sprint?: {
28
59
  authorization?: ZodSchemaType<string, ZodTypeDef, string>;
29
60
  };
30
61
  }
31
- export declare function defineRouteSchema<T extends RouteSchemaOptions>(schema: T): RequestHandler;
62
+ export declare function defineRouteSchema<T extends RouteSchemaOptions>(schema: T): RequestHandler & {
63
+ applyFileUpload?: (sprint: any) => any;
64
+ };
32
65
  export type { ZodSchema, ZodMiddlewareOptions } from './types';
33
66
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/schemas/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,CAAC,EAAE,SAAS,IAAI,aAAa,EAAE,UAAU,EAAuB,MAAM,KAAK,CAAC;AAErF,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;AAED,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;CAC1B,CAAC;AAEF,QAAA,MAAM,MAAM,EAKN,aAAa,CAAC;AAEpB,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,CAAC;AACvB,OAAO,EAAE,aAAa,IAAI,MAAM,EAAE,CAAC;AAEnC,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,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,CA8EzF;AAED,YAAY,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/schemas/index.ts"],"names":[],"mappings":"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"}
@@ -5,8 +5,24 @@ export interface ZodMiddlewareOptions {
5
5
  queryParams?: ZodSchema;
6
6
  params?: ZodSchema;
7
7
  headers?: ZodSchema;
8
+ files?: ZodSchema;
8
9
  sprint?: {
9
10
  authorization?: ZodSchema;
10
11
  };
11
12
  }
13
+ export interface FileValidationOptions {
14
+ ext?: string | string[];
15
+ mimeType?: string | string[];
16
+ maxSize?: number;
17
+ minSize?: number;
18
+ required?: boolean;
19
+ }
20
+ export type FileObject = {
21
+ fieldname: string;
22
+ originalname: string;
23
+ encoding: string;
24
+ mimetype: string;
25
+ size: number;
26
+ buffer?: Buffer;
27
+ };
12
28
  //# 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;AAExB,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,MAAM,CAAC,EAAE;QACL,aAAa,CAAC,EAAE,SAAS,CAAC;KAC7B,CAAC;CACL"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/modules/schemas/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,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;CACtB;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;CACnB,CAAC"}
@@ -1,5 +1,5 @@
1
+ import { default as express, Application, Request, Response } from 'express';
1
2
  import { Handler, MiddlewareConfig } from './types';
2
- import { default as express, Application } from 'express';
3
3
  export declare const isDevelopment: boolean;
4
4
  export declare const isProduction: boolean;
5
5
  export declare class Sprint {
@@ -19,15 +19,17 @@ export declare class Sprint {
19
19
  private graphql;
20
20
  private graphqlSchema;
21
21
  private registeredRoutes;
22
+ fileMemoryUploadedLimit: number;
23
+ memoryUpload: any;
22
24
  constructor();
23
25
  private init;
24
26
  private loadDefaults;
25
27
  /**
26
- * Gets all matching middlewares for a given route path, sorted by priority
28
+ * Gets all matching middlewares for a given route path, sorted by priority.
27
29
  */
28
30
  private getMiddlewaresForRoute;
29
31
  /**
30
- * Load all middleware files from the middlewares folder
32
+ * Load all middleware files from the middlewares folder.
31
33
  */
32
34
  private loadMiddlewares;
33
35
  private loadHealthcheck;
@@ -48,5 +50,23 @@ export declare class Sprint {
48
50
  use(pathOrHandler: string | Handler | MiddlewareConfig, maybeHandler?: Handler): express.Application;
49
51
  setGraphQLSchema(schema: any): void;
50
52
  listen(callback?: () => void): void;
53
+ uploadFile(fieldName?: string): any;
54
+ uploadFiles(fieldNames?: string | string[]): any;
55
+ streamUpload(options?: {
56
+ limits?: {
57
+ fileSize?: number;
58
+ files?: number;
59
+ };
60
+ headers?: Record<string, string>;
61
+ }): (req: Request, res: Response) => Promise<{
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
+ }>;
51
71
  }
52
72
  //# sourceMappingURL=sprint.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sprint.d.ts","sourceRoot":"","sources":["../../src/sprint.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,OAAO,EAA+B,gBAAgB,EAAsC,MAAM,SAAS,CAAC;AACrH,OAAO,OAAO,EAAE,EAAE,WAAW,EAAoD,MAAM,SAAS,CAAC;AAejG,eAAO,MAAM,aAAa,SAAQ,CAAC;AACnC,eAAO,MAAM,YAAY,SAAS,CAAC;AA6CnC,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;;YAuJM,IAAI;IAkDlB,OAAO,CAAC,YAAY;IAiDpB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA4B9B;;OAEG;YACW,eAAe;IAkC7B,OAAO,CAAC,eAAe;YAiBT,UAAU;YAmFV,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;CA+D7C"}
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;YA+GV,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,KAAG,OAAO,CAAC;QAC1C,KAAK,EAAE,KAAK,CAAC;YACT,SAAS,EAAE,MAAM,CAAC;YAClB,IAAI,EAAE,MAAM,CAAC,cAAc,CAAC;YAC5B,QAAQ,EAAE,MAAM,CAAC;YACjB,QAAQ,EAAE,MAAM,CAAC;YACjB,QAAQ,EAAE,MAAM,CAAC;SACpB,CAAC,CAAC;QACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAClC,CAAC;CA0CT"}
@@ -106,6 +106,8 @@ export interface SprintOptions {
106
106
  path?: string;
107
107
  };
108
108
  };
109
+ /** Maximum file size (in bytes) for memory storage uploads. Default: 5MB (5 * 1024 * 1024) */
110
+ fileMemoryUploadedLimit?: number;
109
111
  }
110
112
  export interface SprintConfig {
111
113
  port?: string | number | null;
@@ -133,6 +135,8 @@ export interface SprintConfig {
133
135
  path?: string;
134
136
  };
135
137
  };
138
+ /** Maximum file size (in bytes) for memory storage uploads. Default: 5MB (5 * 1024 * 1024) */
139
+ fileMemoryUploadedLimit?: number;
136
140
  }
137
141
  export type { NextFunction } from 'express';
138
142
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,KAAK,SAAiC,CAAC;AACpD,eAAO,MAAM,SAAS,SAAqC,CAAC;AAE5D,QAAA,IAAI,UAAU,EAAE,MAAM,CAAC;AACvB,QAAA,IAAI,SAAS,EAAE,MAAM,CAAC;AAYtB,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;AAEjC;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAoBxE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAE9E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAS7D"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,KAAK,SAAiC,CAAC;AACpD,eAAO,MAAM,SAAS,SAAqC,CAAC;AAE5D,QAAA,IAAI,UAAU,EAAE,MAAM,CAAC;AACvB,QAAA,IAAI,SAAS,EAAE,MAAM,CAAC;AAYtB,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;AAEjC;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAgBxE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAE9E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAS7D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sprint-es",
3
- "version": "0.0.155",
3
+ "version": "0.0.157",
4
4
  "description": "Sprint - Quickly API",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -109,6 +109,7 @@
109
109
  "dependencies": {
110
110
  "@types/express": "^5.0.5",
111
111
  "axios": "^1.13.2",
112
+ "busboy": "^1.6.0",
112
113
  "cors": "^2.8.5",
113
114
  "dotenv": "^17.3.1",
114
115
  "express": "^5.1.0",
@@ -125,6 +126,7 @@
125
126
  "FJRG2007 (https://github.com/FJRG2007)"
126
127
  ],
127
128
  "devDependencies": {
129
+ "@types/busboy": "^1.5.4",
128
130
  "@types/cors": "^2.8.19",
129
131
  "@types/jest": "^30.0.0",
130
132
  "@types/morgan": "^1.9.10",