express-project-builder 1.0.0

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 (181) hide show
  1. package/dist/bin/index.d.ts +3 -0
  2. package/dist/bin/index.d.ts.map +1 -0
  3. package/dist/bin/index.js +177 -0
  4. package/dist/bin/index.js.map +1 -0
  5. package/dist/lib/config/createEnvExample.d.ts +3 -0
  6. package/dist/lib/config/createEnvExample.d.ts.map +1 -0
  7. package/dist/lib/config/createEnvExample.js +39 -0
  8. package/dist/lib/config/createEnvExample.js.map +1 -0
  9. package/dist/lib/config/createEslintConfig.d.ts +2 -0
  10. package/dist/lib/config/createEslintConfig.d.ts.map +1 -0
  11. package/dist/lib/config/createEslintConfig.js +48 -0
  12. package/dist/lib/config/createEslintConfig.js.map +1 -0
  13. package/dist/lib/config/createGitignore.d.ts +3 -0
  14. package/dist/lib/config/createGitignore.d.ts.map +1 -0
  15. package/dist/lib/config/createGitignore.js +51 -0
  16. package/dist/lib/config/createGitignore.js.map +1 -0
  17. package/dist/lib/config/createPackageJson.d.ts +3 -0
  18. package/dist/lib/config/createPackageJson.d.ts.map +1 -0
  19. package/dist/lib/config/createPackageJson.js +74 -0
  20. package/dist/lib/config/createPackageJson.js.map +1 -0
  21. package/dist/lib/config/createPrettierConfig.d.ts +2 -0
  22. package/dist/lib/config/createPrettierConfig.d.ts.map +1 -0
  23. package/dist/lib/config/createPrettierConfig.js +30 -0
  24. package/dist/lib/config/createPrettierConfig.js.map +1 -0
  25. package/dist/lib/config/createTsConfig.d.ts +2 -0
  26. package/dist/lib/config/createTsConfig.d.ts.map +1 -0
  27. package/dist/lib/config/createTsConfig.js +133 -0
  28. package/dist/lib/config/createTsConfig.js.map +1 -0
  29. package/dist/lib/prisma/create_Schema.Prisma.d.ts +3 -0
  30. package/dist/lib/prisma/create_Schema.Prisma.d.ts.map +1 -0
  31. package/dist/lib/prisma/create_Schema.Prisma.js +36 -0
  32. package/dist/lib/prisma/create_Schema.Prisma.js.map +1 -0
  33. package/dist/lib/src/builders/create_QueryBuilder_Helpers.d.ts +3 -0
  34. package/dist/lib/src/builders/create_QueryBuilder_Helpers.d.ts.map +1 -0
  35. package/dist/lib/src/builders/create_QueryBuilder_Helpers.js +292 -0
  36. package/dist/lib/src/builders/create_QueryBuilder_Helpers.js.map +1 -0
  37. package/dist/lib/src/config/create_Config_Index.d.ts +9 -0
  38. package/dist/lib/src/config/create_Config_Index.d.ts.map +1 -0
  39. package/dist/lib/src/config/create_Config_Index.js +92 -0
  40. package/dist/lib/src/config/create_Config_Index.js.map +1 -0
  41. package/dist/lib/src/constants/create_UserRole_Constant.d.ts +7 -0
  42. package/dist/lib/src/constants/create_UserRole_Constant.d.ts.map +1 -0
  43. package/dist/lib/src/constants/create_UserRole_Constant.js +39 -0
  44. package/dist/lib/src/constants/create_UserRole_Constant.js.map +1 -0
  45. package/dist/lib/src/createAppFile.d.ts +2 -0
  46. package/dist/lib/src/createAppFile.d.ts.map +1 -0
  47. package/dist/lib/src/createAppFile.js +122 -0
  48. package/dist/lib/src/createAppFile.js.map +1 -0
  49. package/dist/lib/src/createServerFile.d.ts +3 -0
  50. package/dist/lib/src/createServerFile.d.ts.map +1 -0
  51. package/dist/lib/src/createServerFile.js +75 -0
  52. package/dist/lib/src/createServerFile.js.map +1 -0
  53. package/dist/lib/src/createSrcStructure.d.ts +2 -0
  54. package/dist/lib/src/createSrcStructure.d.ts.map +1 -0
  55. package/dist/lib/src/createSrcStructure.js +50 -0
  56. package/dist/lib/src/createSrcStructure.js.map +1 -0
  57. package/dist/lib/src/errors/create_AppError_Class.d.ts +7 -0
  58. package/dist/lib/src/errors/create_AppError_Class.d.ts.map +1 -0
  59. package/dist/lib/src/errors/create_AppError_Class.js +65 -0
  60. package/dist/lib/src/errors/create_AppError_Class.js.map +1 -0
  61. package/dist/lib/src/errors/create_HandleCastError.d.ts +9 -0
  62. package/dist/lib/src/errors/create_HandleCastError.d.ts.map +1 -0
  63. package/dist/lib/src/errors/create_HandleCastError.js +101 -0
  64. package/dist/lib/src/errors/create_HandleCastError.js.map +1 -0
  65. package/dist/lib/src/errors/create_HandleDB_ValidationError.d.ts +9 -0
  66. package/dist/lib/src/errors/create_HandleDB_ValidationError.d.ts.map +1 -0
  67. package/dist/lib/src/errors/create_HandleDB_ValidationError.js +119 -0
  68. package/dist/lib/src/errors/create_HandleDB_ValidationError.js.map +1 -0
  69. package/dist/lib/src/errors/create_HandleDuplicateError.d.ts +9 -0
  70. package/dist/lib/src/errors/create_HandleDuplicateError.d.ts.map +1 -0
  71. package/dist/lib/src/errors/create_HandleDuplicateError.js +99 -0
  72. package/dist/lib/src/errors/create_HandleDuplicateError.js.map +1 -0
  73. package/dist/lib/src/errors/create_HandleZodValidationError.d.ts +7 -0
  74. package/dist/lib/src/errors/create_HandleZodValidationError.d.ts.map +1 -0
  75. package/dist/lib/src/errors/create_HandleZodValidationError.js +50 -0
  76. package/dist/lib/src/errors/create_HandleZodValidationError.js.map +1 -0
  77. package/dist/lib/src/interfaces/create_EmailFomat_type.d.ts +7 -0
  78. package/dist/lib/src/interfaces/create_EmailFomat_type.d.ts.map +1 -0
  79. package/dist/lib/src/interfaces/create_EmailFomat_type.js +34 -0
  80. package/dist/lib/src/interfaces/create_EmailFomat_type.js.map +1 -0
  81. package/dist/lib/src/interfaces/create_Errors_type.d.ts +7 -0
  82. package/dist/lib/src/interfaces/create_Errors_type.d.ts.map +1 -0
  83. package/dist/lib/src/interfaces/create_Errors_type.js +43 -0
  84. package/dist/lib/src/interfaces/create_Errors_type.js.map +1 -0
  85. package/dist/lib/src/interfaces/create_Index_d_type.d.ts +9 -0
  86. package/dist/lib/src/interfaces/create_Index_d_type.d.ts.map +1 -0
  87. package/dist/lib/src/interfaces/create_Index_d_type.js +45 -0
  88. package/dist/lib/src/interfaces/create_Index_d_type.js.map +1 -0
  89. package/dist/lib/src/interfaces/create_JWT_Token_type.d.ts +9 -0
  90. package/dist/lib/src/interfaces/create_JWT_Token_type.d.ts.map +1 -0
  91. package/dist/lib/src/interfaces/create_JWT_Token_type.js +33 -0
  92. package/dist/lib/src/interfaces/create_JWT_Token_type.js.map +1 -0
  93. package/dist/lib/src/interfaces/create_UserRole_type.d.ts +7 -0
  94. package/dist/lib/src/interfaces/create_UserRole_type.d.ts.map +1 -0
  95. package/dist/lib/src/interfaces/create_UserRole_type.js +33 -0
  96. package/dist/lib/src/interfaces/create_UserRole_type.js.map +1 -0
  97. package/dist/lib/src/middlewares/create_Auth_Gurad.d.ts +9 -0
  98. package/dist/lib/src/middlewares/create_Auth_Gurad.d.ts.map +1 -0
  99. package/dist/lib/src/middlewares/create_Auth_Gurad.js +99 -0
  100. package/dist/lib/src/middlewares/create_Auth_Gurad.js.map +1 -0
  101. package/dist/lib/src/middlewares/create_BigIntSerializer_Guard.d.ts +7 -0
  102. package/dist/lib/src/middlewares/create_BigIntSerializer_Guard.d.ts.map +1 -0
  103. package/dist/lib/src/middlewares/create_BigIntSerializer_Guard.js +64 -0
  104. package/dist/lib/src/middlewares/create_BigIntSerializer_Guard.js.map +1 -0
  105. package/dist/lib/src/middlewares/create_FormDataToSetJSONformatData_Guard.d.ts +7 -0
  106. package/dist/lib/src/middlewares/create_FormDataToSetJSONformatData_Guard.d.ts.map +1 -0
  107. package/dist/lib/src/middlewares/create_FormDataToSetJSONformatData_Guard.js +63 -0
  108. package/dist/lib/src/middlewares/create_FormDataToSetJSONformatData_Guard.js.map +1 -0
  109. package/dist/lib/src/middlewares/create_Global_ErrorHandler_Guard.d.ts +12 -0
  110. package/dist/lib/src/middlewares/create_Global_ErrorHandler_Guard.d.ts.map +1 -0
  111. package/dist/lib/src/middlewares/create_Global_ErrorHandler_Guard.js +375 -0
  112. package/dist/lib/src/middlewares/create_Global_ErrorHandler_Guard.js.map +1 -0
  113. package/dist/lib/src/middlewares/create_Handle_File_Upload_Middleware.d.ts +7 -0
  114. package/dist/lib/src/middlewares/create_Handle_File_Upload_Middleware.d.ts.map +1 -0
  115. package/dist/lib/src/middlewares/create_Handle_File_Upload_Middleware.js +260 -0
  116. package/dist/lib/src/middlewares/create_Handle_File_Upload_Middleware.js.map +1 -0
  117. package/dist/lib/src/middlewares/create_NotFound_Guard.d.ts +7 -0
  118. package/dist/lib/src/middlewares/create_NotFound_Guard.d.ts.map +1 -0
  119. package/dist/lib/src/middlewares/create_NotFound_Guard.js +47 -0
  120. package/dist/lib/src/middlewares/create_NotFound_Guard.js.map +1 -0
  121. package/dist/lib/src/middlewares/create_RateLimiting_Handler_Guard.d.ts +7 -0
  122. package/dist/lib/src/middlewares/create_RateLimiting_Handler_Guard.d.ts.map +1 -0
  123. package/dist/lib/src/middlewares/create_RateLimiting_Handler_Guard.js +270 -0
  124. package/dist/lib/src/middlewares/create_RateLimiting_Handler_Guard.js.map +1 -0
  125. package/dist/lib/src/middlewares/create_ValidateRequest_Guard.d.ts +7 -0
  126. package/dist/lib/src/middlewares/create_ValidateRequest_Guard.d.ts.map +1 -0
  127. package/dist/lib/src/middlewares/create_ValidateRequest_Guard.js +104 -0
  128. package/dist/lib/src/middlewares/create_ValidateRequest_Guard.js.map +1 -0
  129. package/dist/lib/src/modules/create_DemoModules_SrcStructure.d.ts +7 -0
  130. package/dist/lib/src/modules/create_DemoModules_SrcStructure.d.ts.map +1 -0
  131. package/dist/lib/src/modules/create_DemoModules_SrcStructure.js +367 -0
  132. package/dist/lib/src/modules/create_DemoModules_SrcStructure.js.map +1 -0
  133. package/dist/lib/src/routers/create_Router_Index_Path.d.ts +7 -0
  134. package/dist/lib/src/routers/create_Router_Index_Path.d.ts.map +1 -0
  135. package/dist/lib/src/routers/create_Router_Index_Path.js +54 -0
  136. package/dist/lib/src/routers/create_Router_Index_Path.js.map +1 -0
  137. package/dist/lib/src/shared/create_Prisma_Shated.d.ts +9 -0
  138. package/dist/lib/src/shared/create_Prisma_Shated.d.ts.map +1 -0
  139. package/dist/lib/src/shared/create_Prisma_Shated.js +34 -0
  140. package/dist/lib/src/shared/create_Prisma_Shated.js.map +1 -0
  141. package/dist/lib/src/utils/createCatchAsync_Utils.d.ts +7 -0
  142. package/dist/lib/src/utils/createCatchAsync_Utils.d.ts.map +1 -0
  143. package/dist/lib/src/utils/createCatchAsync_Utils.js +59 -0
  144. package/dist/lib/src/utils/createCatchAsync_Utils.js.map +1 -0
  145. package/dist/lib/src/utils/createLoggerFile.d.ts +7 -0
  146. package/dist/lib/src/utils/createLoggerFile.d.ts.map +1 -0
  147. package/dist/lib/src/utils/createLoggerFile.js +35 -0
  148. package/dist/lib/src/utils/createLoggerFile.js.map +1 -0
  149. package/dist/lib/src/utils/create_Common_Utils.d.ts +9 -0
  150. package/dist/lib/src/utils/create_Common_Utils.d.ts.map +1 -0
  151. package/dist/lib/src/utils/create_Common_Utils.js +262 -0
  152. package/dist/lib/src/utils/create_Common_Utils.js.map +1 -0
  153. package/dist/lib/src/utils/create_Date_Time_Validation_Utils.d.ts +7 -0
  154. package/dist/lib/src/utils/create_Date_Time_Validation_Utils.d.ts.map +1 -0
  155. package/dist/lib/src/utils/create_Date_Time_Validation_Utils.js +181 -0
  156. package/dist/lib/src/utils/create_Date_Time_Validation_Utils.js.map +1 -0
  157. package/dist/lib/src/utils/create_Node_Cache_Utils.d.ts +7 -0
  158. package/dist/lib/src/utils/create_Node_Cache_Utils.d.ts.map +1 -0
  159. package/dist/lib/src/utils/create_Node_Cache_Utils.js +149 -0
  160. package/dist/lib/src/utils/create_Node_Cache_Utils.js.map +1 -0
  161. package/dist/lib/src/utils/create_Remove_Uploaded_Files_Utils.d.ts +7 -0
  162. package/dist/lib/src/utils/create_Remove_Uploaded_Files_Utils.d.ts.map +1 -0
  163. package/dist/lib/src/utils/create_Remove_Uploaded_Files_Utils.js +162 -0
  164. package/dist/lib/src/utils/create_Remove_Uploaded_Files_Utils.js.map +1 -0
  165. package/dist/lib/src/utils/create_SendEmail_Utils.d.ts +7 -0
  166. package/dist/lib/src/utils/create_SendEmail_Utils.d.ts.map +1 -0
  167. package/dist/lib/src/utils/create_SendEmail_Utils.js +140 -0
  168. package/dist/lib/src/utils/create_SendEmail_Utils.js.map +1 -0
  169. package/dist/lib/src/utils/create_sendResponse_Utils.d.ts +7 -0
  170. package/dist/lib/src/utils/create_sendResponse_Utils.d.ts.map +1 -0
  171. package/dist/lib/src/utils/create_sendResponse_Utils.js +95 -0
  172. package/dist/lib/src/utils/create_sendResponse_Utils.js.map +1 -0
  173. package/dist/lib/utils/helpers.d.ts +5 -0
  174. package/dist/lib/utils/helpers.d.ts.map +1 -0
  175. package/dist/lib/utils/helpers.js +31 -0
  176. package/dist/lib/utils/helpers.js.map +1 -0
  177. package/dist/lib/utils/types.d.ts +5 -0
  178. package/dist/lib/utils/types.d.ts.map +1 -0
  179. package/dist/lib/utils/types.js +2 -0
  180. package/dist/lib/utils/types.js.map +1 -0
  181. package/package.json +87 -0
@@ -0,0 +1,260 @@
1
+ import { createFile } from "../../utils/helpers.js";
2
+ import path from "path";
3
+ import chalk from "chalk";
4
+ /**
5
+ * Creates a file upload middleware with dynamic field configuration
6
+ * @param projectPath - Absolute path to the project root
7
+ * @returns Promise that resolves when the file upload middleware file is created
8
+ */
9
+ export const create_Handle_File_Upload_Middleware = async (projectPath) => {
10
+ try {
11
+ const handleFileUploadTemplate = `/* eslint-disable @typescript-eslint/no-explicit-any */
12
+ import multer from 'multer';
13
+ import path from 'path';
14
+ import fs from 'fs/promises';
15
+ import { Request, Response, NextFunction } from 'express';
16
+ import AppError from '../errors/AppError';
17
+ import { removeUploadedFiles } from '../utils/removeUploadedFiles';
18
+
19
+ // Default constants
20
+ const DEFAULT_MAX_IMAGE_SIZE = 5 * 1024 * 1024; // 5MB
21
+ const DEFAULT_MAX_VIDEO_SIZE = 50 * 1024 * 1024; // 50MB
22
+
23
+ // Default allowed file types
24
+ const DEFAULT_ALLOWED_IMAGE_TYPES = [
25
+ 'image/jpeg',
26
+ 'image/png',
27
+ 'image/gif',
28
+ 'image/webp',
29
+ 'image/bmp',
30
+ 'image/svg+xml'
31
+ ];
32
+
33
+ const DEFAULT_ALLOWED_VIDEO_TYPES = [
34
+ 'video/mp4',
35
+ 'video/webm',
36
+ 'video/mov',
37
+ 'video/avi',
38
+ 'video/mkv'
39
+ ];
40
+
41
+ // Helper function to ensure directory exists
42
+ async function ensureDirectoryExists(dirPath: string): Promise<void> {
43
+ try {
44
+ await fs.access(dirPath);
45
+ } catch {
46
+ await fs.mkdir(dirPath, { recursive: true });
47
+ }
48
+ }
49
+
50
+ // Dynamic storage configuration
51
+ const storage = multer.diskStorage({
52
+ destination: async (req: Request, file, cb) => {
53
+ let uploadPath: string;
54
+
55
+ // Determine upload path based on file type
56
+ if (file.mimetype.startsWith('image/')) {
57
+ uploadPath = path.join(process.cwd(), 'uploads/images');
58
+ } else if (file.mimetype.startsWith('video/')) {
59
+ uploadPath = path.join(process.cwd(), 'uploads/videos');
60
+ } else {
61
+ return cb(new AppError(400, '', 'Invalid file type'), '');
62
+ }
63
+
64
+ try {
65
+ await ensureDirectoryExists(uploadPath);
66
+ cb(null, uploadPath);
67
+ } catch (error: any) {
68
+ cb(error, '');
69
+ }
70
+ },
71
+ filename: (req: Request, file, cb) => {
72
+ const ext = path.extname(file.originalname);
73
+ const originalName = path.basename(file.originalname, ext);
74
+ // Use a more unique filename to avoid collisions
75
+ const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
76
+ cb(null, \`\${originalName}-\${uniqueSuffix}\${ext}\`);
77
+ }
78
+ });
79
+
80
+ // Multer instance with global file size limit
81
+ const upload = multer({
82
+ storage,
83
+ limits: { fileSize: DEFAULT_MAX_VIDEO_SIZE },
84
+ fileFilter: (req: Request, file, cb) => {
85
+ // Basic file type validation at the multer level
86
+ if (file.mimetype.startsWith('image/') || file.mimetype.startsWith('video/')) {
87
+ cb(null, true);
88
+ } else {
89
+ cb(new AppError(400, '', 'Invalid file type. Only images and videos are allowed.'));
90
+ }
91
+ }
92
+ });
93
+
94
+ // Field configuration interface
95
+ interface FieldConfig {
96
+ fieldName: string;
97
+ fileType: 'image' | 'video';
98
+ maxCount?: number;
99
+ optional?: boolean;
100
+ maxImageSize?: number;
101
+ maxVideoSize?: number;
102
+ allowedImageTypes?: string[];
103
+ allowedVideoTypes?: string[];
104
+ }
105
+
106
+ // Main dynamic upload handler for multiple fields
107
+ export const handle_file_upload_middleware = (
108
+ fieldConfigs: FieldConfig[],
109
+ globalOptions?: {
110
+ maxImageSize?: number;
111
+ maxVideoSize?: number;
112
+ allowedImageTypes?: string[];
113
+ allowedVideoTypes?: string[];
114
+ }
115
+ ) => {
116
+ // Set global defaults with options
117
+ const globalMaxImageSize = globalOptions?.maxImageSize || DEFAULT_MAX_IMAGE_SIZE;
118
+ const globalMaxVideoSize = globalOptions?.maxVideoSize || DEFAULT_MAX_VIDEO_SIZE;
119
+ const globalAllowedImageTypes = globalOptions?.allowedImageTypes || DEFAULT_ALLOWED_IMAGE_TYPES;
120
+ const globalAllowedVideoTypes = globalOptions?.allowedVideoTypes || DEFAULT_ALLOWED_VIDEO_TYPES;
121
+
122
+ return (req: Request, res: Response, next: NextFunction) => {
123
+ // Prepare multer fields configuration
124
+ const multerFields = fieldConfigs.map(config => ({
125
+ name: config.fieldName,
126
+ maxCount: config.maxCount || 1
127
+ }));
128
+
129
+ // Use multer's fields method to handle all dynamic fields
130
+ upload.fields(multerFields)(req, res, async (err: any) => {
131
+ if (err) {
132
+ // Handle multer errors
133
+ let errorMessage = '';
134
+ let fieldConfig: FieldConfig | undefined;
135
+
136
+ if (err instanceof multer.MulterError) {
137
+ switch (err.code) {
138
+ case 'LIMIT_FILE_SIZE':
139
+ fieldConfig = fieldConfigs.find(f => f.fieldName === err.field);
140
+ errorMessage = \`File size exceeds maximum limit for \${err.field}\`;
141
+ break;
142
+ case 'LIMIT_FILE_COUNT':
143
+ fieldConfig = fieldConfigs.find(f => f.fieldName === err.field);
144
+ errorMessage = \`Too many files uploaded for \${err.field} (max \${fieldConfig?.maxCount || 1})\`;
145
+ break;
146
+ case 'LIMIT_UNEXPECTED_FILE':
147
+ fieldConfig = fieldConfigs.find(f => f.fieldName === err.field);
148
+ if (fieldConfig) {
149
+ errorMessage = \`Too many files uploaded for \${err.field} (max \${fieldConfig.maxCount || 1})\`;
150
+ } else {
151
+ errorMessage = \`Unexpected field name: \${err.field}\`;
152
+ }
153
+ break;
154
+ case 'LIMIT_FIELD_KEY':
155
+ errorMessage = 'Too many fields specified';
156
+ break;
157
+ case 'LIMIT_FIELD_VALUE':
158
+ errorMessage = 'Field value too long';
159
+ break;
160
+ case 'LIMIT_FIELD_COUNT':
161
+ errorMessage = 'Too many fields';
162
+ break;
163
+ case 'LIMIT_PART_COUNT':
164
+ errorMessage = 'Too many parts in form';
165
+ break;
166
+ default:
167
+ errorMessage = \`Upload error: \${err.message}\`;
168
+ }
169
+ } else {
170
+ errorMessage = err.message;
171
+ }
172
+
173
+ return next(new AppError(400, fieldConfig?.fieldName || '', errorMessage));
174
+ }
175
+
176
+ // Get uploaded files with proper typing
177
+ const files = req.files as { [fieldname: string]: Express.Multer.File[] } | undefined;
178
+
179
+ try {
180
+ // Check for required fields
181
+ for (const config of fieldConfigs) {
182
+ if (
183
+ !config.optional &&
184
+ (!files ||
185
+ !files[config.fieldName] ||
186
+ files[config.fieldName].length === 0)
187
+ ) {
188
+ throw new AppError(
189
+ 400,
190
+ config.fieldName,
191
+ \`\${config.fieldName} file field is required\`
192
+ );
193
+ }
194
+ }
195
+
196
+ // Validate each file in each field
197
+ for (const config of fieldConfigs) {
198
+ const fieldFiles = files?.[config.fieldName] || [];
199
+
200
+ // Determine the max size for this field
201
+ const maxSize = config.fileType === 'image'
202
+ ? (config.maxImageSize || globalMaxImageSize)
203
+ : (config.maxVideoSize || globalMaxVideoSize);
204
+
205
+ // Determine allowed types for this field
206
+ const allowedTypes = config.fileType === 'image'
207
+ ? (config.allowedImageTypes || globalAllowedImageTypes)
208
+ : (config.allowedVideoTypes || globalAllowedVideoTypes);
209
+
210
+ for (const file of fieldFiles) {
211
+ // Validate file type
212
+ if (!allowedTypes.includes(file.mimetype)) {
213
+ // Create a user-friendly list of allowed extensions
214
+ const allowedExtensions = allowedTypes.map(type => {
215
+ const parts = type.split('/');
216
+ return parts[1] || type;
217
+ }).join(', ');
218
+
219
+ throw new AppError(
220
+ 400,
221
+ config.fieldName,
222
+ \`Invalid file type for \${config.fieldName}. Only \${allowedExtensions} files are allowed\`
223
+ );
224
+ }
225
+
226
+ // Validate file size
227
+ if (file.size > maxSize) {
228
+ throw new AppError(
229
+ 400,
230
+ config.fieldName,
231
+ \`File size exceeds maximum limit for \${config.fieldName} (\${maxSize / (1024 * 1024)}MB)\`
232
+ );
233
+ }
234
+ }
235
+ }
236
+
237
+ // If validation passes, proceed to next middleware
238
+ next();
239
+ } catch (validationError) {
240
+ // Clean up all uploaded files on validation error
241
+ if (files) {
242
+ await removeUploadedFiles(files);
243
+ }
244
+ next(validationError);
245
+ }
246
+ });
247
+ };
248
+ };
249
+ `;
250
+ await createFile(path.join(projectPath, "src/app/middlewares", "handleFileUpload.ts"), handleFileUploadTemplate);
251
+ // Success message with green checkmark and text
252
+ console.log(chalk.green("✅ Handle File Upload Middleware file created successfully"));
253
+ }
254
+ catch (err) {
255
+ // Error message with red cross and text
256
+ console.error(chalk.red("❌ Error creating Handle File Upload Middleware file:"), err);
257
+ throw err;
258
+ }
259
+ };
260
+ //# sourceMappingURL=create_Handle_File_Upload_Middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_Handle_File_Upload_Middleware.js","sourceRoot":"","sources":["../../../../src/lib/src/middlewares/create_Handle_File_Upload_Middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;;GAIG;AACH,MAAM,CAAC,MAAM,oCAAoC,GAAG,KAAK,EACvD,WAAmB,EACJ,EAAE;IACjB,IAAI,CAAC;QACH,MAAM,wBAAwB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8OpC,CAAC;QAEE,MAAM,UAAU,CACd,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,qBAAqB,EAAE,qBAAqB,CAAC,EACpE,wBAAwB,CACzB,CAAC;QAEF,gDAAgD;QAChD,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,KAAK,CAAC,2DAA2D,CAAC,CACzE,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,wCAAwC;QACxC,OAAO,CAAC,KAAK,CACX,KAAK,CAAC,GAAG,CAAC,sDAAsD,CAAC,EACjE,GAAG,CACJ,CAAC;QACF,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Creates a not found middleware file for handling 404 errors
3
+ * @param projectPath - Absolute path to the project root
4
+ * @returns Promise that resolves when the not found middleware file is created
5
+ */
6
+ export declare const create_NotFound_Guard: (projectPath: string) => Promise<void>;
7
+ //# sourceMappingURL=create_NotFound_Guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_NotFound_Guard.d.ts","sourceRoot":"","sources":["../../../../src/lib/src/middlewares/create_NotFound_Guard.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAChC,aAAa,MAAM,KAClB,OAAO,CAAC,IAAI,CA8Cd,CAAC"}
@@ -0,0 +1,47 @@
1
+ import path from "path";
2
+ import { createFile } from "../../utils/helpers.js";
3
+ import chalk from "chalk";
4
+ /**
5
+ * Creates a not found middleware file for handling 404 errors
6
+ * @param projectPath - Absolute path to the project root
7
+ * @returns Promise that resolves when the not found middleware file is created
8
+ */
9
+ export const create_NotFound_Guard = async (projectPath) => {
10
+ try {
11
+ const notFoundMiddlewareTemplate = `/* eslint-disable @typescript-eslint/no-unused-vars */
12
+ import { NextFunction, Request, Response } from 'express';
13
+
14
+ /**
15
+ * Not Found middleware
16
+ * Handles requests to non-existent routes and returns a consistent 404 response
17
+ *
18
+ * @param req - Express Request object
19
+ * @param res - Express Response object
20
+ * @param next - Express NextFunction
21
+ */
22
+ const notFound = (req: Request, res: Response, next: NextFunction) => {
23
+ res.status(404).json({
24
+ status: 404,
25
+ success: false,
26
+ message: 'API Not Found!',
27
+ error: {
28
+ path: req.originalUrl,
29
+ message: 'Your requested API not found',
30
+ method: req.method
31
+ }
32
+ });
33
+ };
34
+
35
+ export default notFound;
36
+ `;
37
+ await createFile(path.join(projectPath, "src/app/middlewares", "notFound.ts"), notFoundMiddlewareTemplate);
38
+ // Success message with green checkmark and text
39
+ console.log(chalk.green("✅ Not Found Middleware file created successfully"));
40
+ }
41
+ catch (err) {
42
+ // Error message with red cross and text
43
+ console.error(chalk.red("❌ Error creating Not Found Middleware file:"), err);
44
+ throw err;
45
+ }
46
+ };
47
+ //# sourceMappingURL=create_NotFound_Guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_NotFound_Guard.js","sourceRoot":"","sources":["../../../../src/lib/src/middlewares/create_NotFound_Guard.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EACxC,WAAmB,EACJ,EAAE;IACjB,IAAI,CAAC;QACH,MAAM,0BAA0B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;CAyBtC,CAAC;QAEE,MAAM,UAAU,CACd,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,qBAAqB,EAAE,aAAa,CAAC,EAC5D,0BAA0B,CAC3B,CAAC;QAEF,gDAAgD;QAChD,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAChE,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,wCAAwC;QACxC,OAAO,CAAC,KAAK,CACX,KAAK,CAAC,GAAG,CAAC,6CAA6C,CAAC,EACxD,GAAG,CACJ,CAAC;QACF,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Creates a progressive rate limiter middleware file
3
+ * @param projectPath - Absolute path to the project root
4
+ * @returns Promise that resolves when the rate limiting handler file is created
5
+ */
6
+ export declare const create_RateLimiting_Handler_Guard: (projectPath: string) => Promise<void>;
7
+ //# sourceMappingURL=create_RateLimiting_Handler_Guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_RateLimiting_Handler_Guard.d.ts","sourceRoot":"","sources":["../../../../src/lib/src/middlewares/create_RateLimiting_Handler_Guard.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,eAAO,MAAM,iCAAiC,GAC5C,aAAa,MAAM,KAClB,OAAO,CAAC,IAAI,CA6Qd,CAAC"}
@@ -0,0 +1,270 @@
1
+ import path from "path";
2
+ import { createFile } from "../../utils/helpers.js";
3
+ import chalk from "chalk";
4
+ /**
5
+ * Creates a progressive rate limiter middleware file
6
+ * @param projectPath - Absolute path to the project root
7
+ * @returns Promise that resolves when the rate limiting handler file is created
8
+ */
9
+ export const create_RateLimiting_Handler_Guard = async (projectPath) => {
10
+ try {
11
+ const rateLimitingHandlerTemplate = `import { NextFunction, Request, Response } from 'express';
12
+
13
+ /**
14
+ * Creates a progressive rate limiter with increasing block durations
15
+ * @param options Configuration options
16
+ * @returns Express middleware function
17
+ */
18
+ export const createProgressiveRateLimiter = (
19
+ options: {
20
+ initialWindowMs?: number; // Time window for counting requests
21
+ initialMax?: number; // Max requests per window
22
+ initialBlockMs?: number; // Initial block duration
23
+ message?: string | object; // Custom message when blocked
24
+ skipSuccessfulRequests?: boolean;
25
+ skipFailedRequests?: boolean;
26
+ keyGenerator?: (req: Request) => string;
27
+ } = {}
28
+ ) => {
29
+ // Set default values
30
+ const {
31
+ initialWindowMs = 60 * 1000, // 1 minute by default
32
+ initialMax = 15, // 15 requests by default
33
+ initialBlockMs = 20 * 60 * 1000, // 20 minutes initial block
34
+ message = {
35
+ success: false,
36
+ message: 'Too many requests. You are temporarily blocked.'
37
+ },
38
+ skipSuccessfulRequests = false,
39
+ skipFailedRequests = false,
40
+ keyGenerator = (req: Request) =>
41
+ req.ip || req.connection.remoteAddress || 'unknown'
42
+ } = options;
43
+
44
+ // Store for tracking request counts and blocked IPs
45
+ const requestCounts = new Map<string, { count: number; resetTime: number }>();
46
+ const blockedIPs = new Map<
47
+ string,
48
+ {
49
+ unblockTime: number;
50
+ blockHistory: { duration: number; timestamp: number }[];
51
+ }
52
+ >();
53
+
54
+ // Cleanup function to remove old entries
55
+ const cleanup = () => {
56
+ const now = Date.now();
57
+
58
+ // Clean up request counts
59
+ for (const [key, value] of requestCounts.entries()) {
60
+ if (value.resetTime < now) {
61
+ requestCounts.delete(key);
62
+ }
63
+ }
64
+
65
+ // Clean up blocked IPs
66
+ for (const [key, value] of blockedIPs.entries()) {
67
+ if (value.unblockTime < now) {
68
+ // Keep block history but remove the block
69
+ blockedIPs.delete(key);
70
+ }
71
+ }
72
+ };
73
+
74
+ // Run cleanup every minute
75
+ setInterval(cleanup, 60 * 1000);
76
+
77
+ // Function to determine next block duration based on history
78
+ const calculateNextBlockDuration = (
79
+ blockHistory: { duration: number; timestamp: number }[]
80
+ ): number => {
81
+ const now = Date.now();
82
+
83
+ // Filter out old blocks (older than 30 days)
84
+ const recentBlocks = blockHistory.filter(
85
+ block => now - block.timestamp < 30 * 24 * 60 * 60 * 1000
86
+ );
87
+
88
+ // Count blocks by duration type
89
+ const twentyMinBlocks = recentBlocks.filter(
90
+ b => b.duration === initialBlockMs
91
+ ).length;
92
+ const oneDayBlocks = recentBlocks.filter(
93
+ b => b.duration === 24 * 60 * 60 * 1000
94
+ ).length;
95
+ const sevenDayBlocks = recentBlocks.filter(
96
+ b => b.duration === 7 * 24 * 60 * 60 * 1000
97
+ ).length;
98
+ const oneMonthBlocks = recentBlocks.filter(
99
+ b => b.duration === 30 * 24 * 60 * 60 * 1000
100
+ ).length;
101
+
102
+ // Progressive blocking logic
103
+ if (oneMonthBlocks >= 3) {
104
+ // 1 year block
105
+ return 365 * 24 * 60 * 60 * 1000;
106
+ } else if (sevenDayBlocks >= 3) {
107
+ // 1 month block
108
+ return 30 * 24 * 60 * 60 * 1000;
109
+ } else if (oneDayBlocks >= 3) {
110
+ // 7 days block
111
+ return 7 * 24 * 60 * 60 * 1000;
112
+ } else if (twentyMinBlocks >= 5) {
113
+ // 1 day block
114
+ return 24 * 60 * 60 * 1000;
115
+ } else {
116
+ // Default 20 minutes block
117
+ return initialBlockMs;
118
+ }
119
+ };
120
+
121
+ // Function to get block message based on duration
122
+ const getBlockMessage = (duration: number): string | object => {
123
+ if (typeof message === 'string') {
124
+ return message;
125
+ }
126
+
127
+ let blockDurationText = '';
128
+ if (duration >= 365 * 24 * 60 * 60 * 1000) {
129
+ blockDurationText = '1 year';
130
+ } else if (duration >= 30 * 24 * 60 * 60 * 1000) {
131
+ blockDurationText = '1 month';
132
+ } else if (duration >= 7 * 24 * 60 * 60 * 1000) {
133
+ blockDurationText = '7 days';
134
+ } else if (duration >= 24 * 60 * 60 * 1000) {
135
+ blockDurationText = '1 day';
136
+ } else {
137
+ blockDurationText = \`\${initialBlockMs ? initialBlockMs / 60000 : 20} minutes\`;
138
+ }
139
+
140
+ return {
141
+ ...message,
142
+ message: \`Too many requests. You are blocked for \${blockDurationText}.\`
143
+ };
144
+ };
145
+
146
+ // Helper function to set rate limit headers
147
+ const setRateLimitHeaders = (
148
+ res: Response,
149
+ limit: number,
150
+ remaining: number,
151
+ resetTime: number,
152
+ retryAfter?: number
153
+ ) => {
154
+ res.setHeader('X-RateLimit-Limit', limit.toString());
155
+ res.setHeader('X-RateLimit-Remaining', remaining.toString());
156
+ res.setHeader('X-RateLimit-Reset', Math.ceil(resetTime / 1000).toString());
157
+ if (retryAfter) {
158
+ res.setHeader('Retry-After', retryAfter.toString());
159
+ }
160
+ };
161
+
162
+ return (req: Request, res: Response, next: NextFunction) => {
163
+ const key = keyGenerator(req);
164
+ const now = Date.now();
165
+
166
+ // Check if IP is blocked
167
+ if (blockedIPs.has(key)) {
168
+ const blockInfo = blockedIPs.get(key)!;
169
+ if (blockInfo.unblockTime > now) {
170
+ const retryAfter = Math.ceil((blockInfo.unblockTime - now) / 1000);
171
+ setRateLimitHeaders(
172
+ res,
173
+ initialMax,
174
+ 0,
175
+ blockInfo.unblockTime,
176
+ retryAfter
177
+ );
178
+ res.status(429).json(getBlockMessage(blockInfo.unblockTime - now));
179
+ return;
180
+ } else {
181
+ // Unblock if time has passed
182
+ blockedIPs.delete(key);
183
+ }
184
+ }
185
+
186
+ // Get or create request count info
187
+ let countInfo = requestCounts.get(key);
188
+ if (!countInfo || countInfo.resetTime < now) {
189
+ // New window
190
+ countInfo = {
191
+ count: 1,
192
+ resetTime: now + initialWindowMs
193
+ };
194
+ requestCounts.set(key, countInfo);
195
+ // Set headers for new window
196
+ setRateLimitHeaders(res, initialMax, initialMax - 1, countInfo.resetTime);
197
+ next();
198
+ return;
199
+ }
200
+
201
+ // Increment count
202
+ countInfo.count++;
203
+
204
+ // Set headers for existing window
205
+ setRateLimitHeaders(
206
+ res,
207
+ initialMax,
208
+ Math.max(0, initialMax - countInfo.count),
209
+ countInfo.resetTime
210
+ );
211
+
212
+ // Check if we should skip counting this request
213
+ const isSuccess = res.statusCode < 400;
214
+ if (
215
+ (skipSuccessfulRequests && isSuccess) ||
216
+ (skipFailedRequests && !isSuccess)
217
+ ) {
218
+ next();
219
+ return;
220
+ }
221
+
222
+ // Check if limit exceeded
223
+ if (countInfo.count > initialMax) {
224
+ // Get existing block history or create new one
225
+ let blockHistory: { duration: number; timestamp: number }[] = [];
226
+ if (blockedIPs.has(key)) {
227
+ blockHistory = blockedIPs.get(key)!.blockHistory;
228
+ }
229
+
230
+ // Calculate next block duration based on history
231
+ const blockDuration = calculateNextBlockDuration(blockHistory);
232
+
233
+ // Add this block to history
234
+ blockHistory.push({
235
+ duration: blockDuration,
236
+ timestamp: now
237
+ });
238
+
239
+ // Block the IP
240
+ const unblockTime = now + blockDuration;
241
+ blockedIPs.set(key, {
242
+ unblockTime,
243
+ blockHistory
244
+ });
245
+
246
+ // Remove from request counts to save memory
247
+ requestCounts.delete(key);
248
+
249
+ // Set headers for blocked IP
250
+ const retryAfter = Math.ceil(blockDuration / 1000);
251
+ setRateLimitHeaders(res, initialMax, 0, unblockTime, retryAfter);
252
+ res.status(429).json(getBlockMessage(blockDuration));
253
+ return;
254
+ }
255
+
256
+ next();
257
+ };
258
+ };
259
+ `;
260
+ await createFile(path.join(projectPath, "src/app/middlewares", "rateLimitingHandler.ts"), rateLimitingHandlerTemplate);
261
+ // Success message with green checkmark and text
262
+ console.log(chalk.green("✅ Rate Limiting Handler file created successfully"));
263
+ }
264
+ catch (err) {
265
+ // Error message with red cross and text
266
+ console.error(chalk.red("❌ Error creating Rate Limiting Handler file:"), err);
267
+ throw err;
268
+ }
269
+ };
270
+ //# sourceMappingURL=create_RateLimiting_Handler_Guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_RateLimiting_Handler_Guard.js","sourceRoot":"","sources":["../../../../src/lib/src/middlewares/create_RateLimiting_Handler_Guard.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;;GAIG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAAG,KAAK,EACpD,WAAmB,EACJ,EAAE;IACjB,IAAI,CAAC;QACH,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwPvC,CAAC;QAEE,MAAM,UAAU,CACd,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,qBAAqB,EAAE,wBAAwB,CAAC,EACvE,2BAA2B,CAC5B,CAAC;QAEF,gDAAgD;QAChD,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,KAAK,CAAC,mDAAmD,CAAC,CACjE,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,wCAAwC;QACxC,OAAO,CAAC,KAAK,CACX,KAAK,CAAC,GAAG,CAAC,8CAA8C,CAAC,EACzD,GAAG,CACJ,CAAC;QACF,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Creates a request validation middleware file using Zod schemas
3
+ * @param projectPath - Absolute path to the project root
4
+ * @returns Promise that resolves when the validate request middleware file is created
5
+ */
6
+ export declare const create_ValidateRequest_Guard: (projectPath: string) => Promise<void>;
7
+ //# sourceMappingURL=create_ValidateRequest_Guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_ValidateRequest_Guard.d.ts","sourceRoot":"","sources":["../../../../src/lib/src/middlewares/create_ValidateRequest_Guard.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,GACvC,aAAa,MAAM,KAClB,OAAO,CAAC,IAAI,CAuGd,CAAC"}