@exyconn/common 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 (88) hide show
  1. package/README.md +259 -0
  2. package/dist/client/http/index.d.mts +85 -0
  3. package/dist/client/http/index.d.ts +85 -0
  4. package/dist/client/http/index.js +127 -0
  5. package/dist/client/http/index.js.map +1 -0
  6. package/dist/client/http/index.mjs +109 -0
  7. package/dist/client/http/index.mjs.map +1 -0
  8. package/dist/client/index.d.mts +7 -0
  9. package/dist/client/index.d.ts +7 -0
  10. package/dist/client/index.js +964 -0
  11. package/dist/client/index.js.map +1 -0
  12. package/dist/client/index.mjs +889 -0
  13. package/dist/client/index.mjs.map +1 -0
  14. package/dist/client/logger/index.d.mts +53 -0
  15. package/dist/client/logger/index.d.ts +53 -0
  16. package/dist/client/logger/index.js +120 -0
  17. package/dist/client/logger/index.js.map +1 -0
  18. package/dist/client/logger/index.mjs +116 -0
  19. package/dist/client/logger/index.mjs.map +1 -0
  20. package/dist/client/utils/index.d.mts +285 -0
  21. package/dist/client/utils/index.d.ts +285 -0
  22. package/dist/client/utils/index.js +403 -0
  23. package/dist/client/utils/index.js.map +1 -0
  24. package/dist/client/utils/index.mjs +362 -0
  25. package/dist/client/utils/index.mjs.map +1 -0
  26. package/dist/index-BNdT-2X4.d.ts +229 -0
  27. package/dist/index-CcrANHAQ.d.mts +59 -0
  28. package/dist/index-ClWtDfwk.d.ts +833 -0
  29. package/dist/index-DSW6JfD-.d.mts +833 -0
  30. package/dist/index-Du0LLt9f.d.mts +229 -0
  31. package/dist/index-iTKxFa78.d.ts +59 -0
  32. package/dist/index.d.mts +171 -0
  33. package/dist/index.d.ts +171 -0
  34. package/dist/index.js +3806 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/index.mjs +3792 -0
  37. package/dist/index.mjs.map +1 -0
  38. package/dist/response.types-D--UhLJq.d.mts +67 -0
  39. package/dist/response.types-D--UhLJq.d.ts +67 -0
  40. package/dist/server/db/index.d.mts +38 -0
  41. package/dist/server/db/index.d.ts +38 -0
  42. package/dist/server/db/index.js +68 -0
  43. package/dist/server/db/index.js.map +1 -0
  44. package/dist/server/db/index.mjs +60 -0
  45. package/dist/server/db/index.mjs.map +1 -0
  46. package/dist/server/enums/index.d.mts +46 -0
  47. package/dist/server/enums/index.d.ts +46 -0
  48. package/dist/server/enums/index.js +48 -0
  49. package/dist/server/enums/index.js.map +1 -0
  50. package/dist/server/enums/index.mjs +43 -0
  51. package/dist/server/enums/index.mjs.map +1 -0
  52. package/dist/server/index.d.mts +9 -0
  53. package/dist/server/index.d.ts +9 -0
  54. package/dist/server/index.js +569 -0
  55. package/dist/server/index.js.map +1 -0
  56. package/dist/server/index.mjs +523 -0
  57. package/dist/server/index.mjs.map +1 -0
  58. package/dist/server/logger/index.d.mts +34 -0
  59. package/dist/server/logger/index.d.ts +34 -0
  60. package/dist/server/logger/index.js +125 -0
  61. package/dist/server/logger/index.js.map +1 -0
  62. package/dist/server/logger/index.mjs +113 -0
  63. package/dist/server/logger/index.mjs.map +1 -0
  64. package/dist/server/middleware/index.d.mts +56 -0
  65. package/dist/server/middleware/index.d.ts +56 -0
  66. package/dist/server/middleware/index.js +128 -0
  67. package/dist/server/middleware/index.js.map +1 -0
  68. package/dist/server/middleware/index.mjs +118 -0
  69. package/dist/server/middleware/index.mjs.map +1 -0
  70. package/dist/server/response/index.d.mts +86 -0
  71. package/dist/server/response/index.d.ts +86 -0
  72. package/dist/server/response/index.js +140 -0
  73. package/dist/server/response/index.js.map +1 -0
  74. package/dist/server/response/index.mjs +126 -0
  75. package/dist/server/response/index.mjs.map +1 -0
  76. package/dist/server/utils/index.d.mts +69 -0
  77. package/dist/server/utils/index.d.ts +69 -0
  78. package/dist/server/utils/index.js +114 -0
  79. package/dist/server/utils/index.js.map +1 -0
  80. package/dist/server/utils/index.mjs +106 -0
  81. package/dist/server/utils/index.mjs.map +1 -0
  82. package/dist/shared/index.d.mts +4 -0
  83. package/dist/shared/index.d.ts +4 -0
  84. package/dist/shared/index.js +933 -0
  85. package/dist/shared/index.js.map +1 -0
  86. package/dist/shared/index.mjs +612 -0
  87. package/dist/shared/index.mjs.map +1 -0
  88. package/package.json +202 -0
@@ -0,0 +1,569 @@
1
+ 'use strict';
2
+
3
+ var winston = require('winston');
4
+ var DailyRotateFile = require('winston-daily-rotate-file');
5
+ var path = require('path');
6
+ var mongoose = require('mongoose');
7
+ var jwt = require('jsonwebtoken');
8
+
9
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
+
11
+ var winston__default = /*#__PURE__*/_interopDefault(winston);
12
+ var DailyRotateFile__default = /*#__PURE__*/_interopDefault(DailyRotateFile);
13
+ var path__default = /*#__PURE__*/_interopDefault(path);
14
+ var mongoose__default = /*#__PURE__*/_interopDefault(mongoose);
15
+ var jwt__default = /*#__PURE__*/_interopDefault(jwt);
16
+
17
+ // src/server/enums/status.ts
18
+ var StatusCode = /* @__PURE__ */ ((StatusCode2) => {
19
+ StatusCode2[StatusCode2["SUCCESS"] = 200] = "SUCCESS";
20
+ StatusCode2[StatusCode2["CREATED"] = 201] = "CREATED";
21
+ StatusCode2[StatusCode2["ACCEPTED"] = 202] = "ACCEPTED";
22
+ StatusCode2[StatusCode2["NO_CONTENT"] = 204] = "NO_CONTENT";
23
+ StatusCode2[StatusCode2["BAD_REQUEST"] = 400] = "BAD_REQUEST";
24
+ StatusCode2[StatusCode2["UNAUTHORIZED"] = 401] = "UNAUTHORIZED";
25
+ StatusCode2[StatusCode2["FORBIDDEN"] = 403] = "FORBIDDEN";
26
+ StatusCode2[StatusCode2["NOT_FOUND"] = 404] = "NOT_FOUND";
27
+ StatusCode2[StatusCode2["CONFLICT"] = 409] = "CONFLICT";
28
+ StatusCode2[StatusCode2["UNPROCESSABLE_ENTITY"] = 422] = "UNPROCESSABLE_ENTITY";
29
+ StatusCode2[StatusCode2["TOO_MANY_REQUESTS"] = 429] = "TOO_MANY_REQUESTS";
30
+ StatusCode2[StatusCode2["INTERNAL_ERROR"] = 500] = "INTERNAL_ERROR";
31
+ StatusCode2[StatusCode2["NOT_IMPLEMENTED"] = 501] = "NOT_IMPLEMENTED";
32
+ StatusCode2[StatusCode2["BAD_GATEWAY"] = 502] = "BAD_GATEWAY";
33
+ StatusCode2[StatusCode2["SERVICE_UNAVAILABLE"] = 503] = "SERVICE_UNAVAILABLE";
34
+ return StatusCode2;
35
+ })(StatusCode || {});
36
+ var StatusMessage = /* @__PURE__ */ ((StatusMessage2) => {
37
+ StatusMessage2["SUCCESS"] = "success";
38
+ StatusMessage2["CREATED"] = "created";
39
+ StatusMessage2["ACCEPTED"] = "accepted";
40
+ StatusMessage2["NO_CONTENT"] = "no-data-found";
41
+ StatusMessage2["BAD_REQUEST"] = "bad-request";
42
+ StatusMessage2["UNAUTHORIZED"] = "unauthorized";
43
+ StatusMessage2["FORBIDDEN"] = "forbidden";
44
+ StatusMessage2["NOT_FOUND"] = "not-found";
45
+ StatusMessage2["CONFLICT"] = "conflict";
46
+ StatusMessage2["UNPROCESSABLE_ENTITY"] = "validation-error";
47
+ StatusMessage2["TOO_MANY_REQUESTS"] = "rate-limit-exceeded";
48
+ StatusMessage2["INTERNAL_ERROR"] = "error";
49
+ StatusMessage2["NOT_IMPLEMENTED"] = "not-implemented";
50
+ StatusMessage2["BAD_GATEWAY"] = "bad-gateway";
51
+ StatusMessage2["SERVICE_UNAVAILABLE"] = "service-unavailable";
52
+ return StatusMessage2;
53
+ })(StatusMessage || {});
54
+ var statusCode = StatusCode;
55
+ var statusMessage = StatusMessage;
56
+
57
+ // src/server/response/response-object.ts
58
+ var extractColumns = (data) => {
59
+ if (!Array.isArray(data) || data.length === 0) {
60
+ return [];
61
+ }
62
+ const sample = data[0];
63
+ return Object.entries(sample).map(([key, value]) => {
64
+ let datatype = typeof value;
65
+ if (value === null) {
66
+ datatype = "null";
67
+ } else if (Array.isArray(value)) {
68
+ datatype = "array";
69
+ } else if (value instanceof Date) {
70
+ datatype = "date";
71
+ } else if (typeof value === "object") {
72
+ datatype = "object";
73
+ }
74
+ return {
75
+ name: key,
76
+ datatype,
77
+ required: value !== null && value !== void 0
78
+ };
79
+ });
80
+ };
81
+ var successResponse = (res, data, message = "Operation successful") => {
82
+ return res.status(200 /* SUCCESS */).json({
83
+ message,
84
+ data,
85
+ status: "success" /* SUCCESS */,
86
+ statusCode: 200 /* SUCCESS */
87
+ });
88
+ };
89
+ var successResponseArr = (res, data, paginationData = {}, message = "Operation successful") => {
90
+ return res.status(200 /* SUCCESS */).json({
91
+ message,
92
+ data,
93
+ columns: extractColumns(data),
94
+ paginationData,
95
+ status: "success" /* SUCCESS */,
96
+ statusCode: 200 /* SUCCESS */
97
+ });
98
+ };
99
+ var createdResponse = (res, data, message = "Resource created successfully") => {
100
+ return res.status(201 /* CREATED */).json({
101
+ message,
102
+ data,
103
+ status: "created" /* CREATED */,
104
+ statusCode: 201 /* CREATED */
105
+ });
106
+ };
107
+ var noContentResponse = (res, data = null, message = "No data found") => {
108
+ return res.status(200 /* SUCCESS */).json({
109
+ message,
110
+ data,
111
+ status: "no-data-found" /* NO_CONTENT */,
112
+ statusCode: 204 /* NO_CONTENT */
113
+ });
114
+ };
115
+ var badRequestResponse = (res, message = "Bad request", errors = null) => {
116
+ return res.status(400 /* BAD_REQUEST */).json({
117
+ message,
118
+ data: errors,
119
+ status: "bad-request" /* BAD_REQUEST */,
120
+ statusCode: 400 /* BAD_REQUEST */
121
+ });
122
+ };
123
+ var unauthorizedResponse = (res, message = "Unauthorized access") => {
124
+ return res.status(401 /* UNAUTHORIZED */).json({
125
+ message,
126
+ data: null,
127
+ status: "unauthorized" /* UNAUTHORIZED */,
128
+ statusCode: 401 /* UNAUTHORIZED */
129
+ });
130
+ };
131
+ var forbiddenResponse = (res, message = "Access forbidden") => {
132
+ return res.status(403 /* FORBIDDEN */).json({
133
+ message,
134
+ data: null,
135
+ status: "forbidden" /* FORBIDDEN */,
136
+ statusCode: 403 /* FORBIDDEN */
137
+ });
138
+ };
139
+ var notFoundResponse = (res, message = "Resource not found") => {
140
+ return res.status(404 /* NOT_FOUND */).json({
141
+ message,
142
+ data: null,
143
+ status: "not-found" /* NOT_FOUND */,
144
+ statusCode: 404 /* NOT_FOUND */
145
+ });
146
+ };
147
+ var conflictResponse = (res, message = "Resource conflict") => {
148
+ return res.status(409 /* CONFLICT */).json({
149
+ message,
150
+ data: null,
151
+ status: "conflict" /* CONFLICT */,
152
+ statusCode: 409 /* CONFLICT */
153
+ });
154
+ };
155
+ var validationErrorResponse = (res, errors, message = "Validation failed") => {
156
+ return res.status(422 /* UNPROCESSABLE_ENTITY */).json({
157
+ message,
158
+ data: errors,
159
+ status: "validation-error" /* UNPROCESSABLE_ENTITY */,
160
+ statusCode: 422 /* UNPROCESSABLE_ENTITY */
161
+ });
162
+ };
163
+ var errorResponse = (res, error = null, message = "Something went wrong") => {
164
+ return res.status(500 /* INTERNAL_ERROR */).json({
165
+ message,
166
+ data: error,
167
+ status: "error" /* INTERNAL_ERROR */,
168
+ statusCode: 500 /* INTERNAL_ERROR */
169
+ });
170
+ };
171
+ var rateLimitResponse = (res, message = "Too many requests, please try again later") => {
172
+ return res.status(429 /* TOO_MANY_REQUESTS */).json({
173
+ message,
174
+ data: null,
175
+ status: "rate-limit-exceeded" /* TOO_MANY_REQUESTS */,
176
+ statusCode: 429 /* TOO_MANY_REQUESTS */
177
+ });
178
+ };
179
+ var defaultConfig = {
180
+ level: process.env.LOG_LEVEL || "info",
181
+ logsDir: "logs",
182
+ maxSize: "20m",
183
+ maxFiles: "14d",
184
+ errorMaxFiles: "30d"
185
+ };
186
+ var levels = {
187
+ error: 0,
188
+ warn: 1,
189
+ info: 2,
190
+ http: 3,
191
+ debug: 4
192
+ };
193
+ var colors = {
194
+ error: "red",
195
+ warn: "yellow",
196
+ info: "green",
197
+ http: "magenta",
198
+ debug: "blue"
199
+ };
200
+ winston__default.default.addColors(colors);
201
+ var fileFormat = winston__default.default.format.combine(
202
+ winston__default.default.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
203
+ winston__default.default.format.errors({ stack: true }),
204
+ winston__default.default.format.splat(),
205
+ winston__default.default.format.json()
206
+ );
207
+ var consoleFormat = winston__default.default.format.combine(
208
+ winston__default.default.format.colorize({ all: true }),
209
+ winston__default.default.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
210
+ winston__default.default.format.printf((info) => {
211
+ const timestamp = info.timestamp;
212
+ const level = info.level;
213
+ const message = info.message;
214
+ const stack = info.stack;
215
+ return `${timestamp} [${level}]: ${message}${stack ? "\n" + stack : ""}`;
216
+ })
217
+ );
218
+ var createLogger = (config = {}) => {
219
+ const finalConfig = { ...defaultConfig, ...config };
220
+ const transports = [
221
+ // Console transport
222
+ new winston__default.default.transports.Console({
223
+ format: consoleFormat
224
+ }),
225
+ // Combined logs (all levels)
226
+ new DailyRotateFile__default.default({
227
+ filename: path__default.default.join(finalConfig.logsDir, "combined-%DATE%.log"),
228
+ datePattern: "YYYY-MM-DD",
229
+ maxSize: finalConfig.maxSize,
230
+ maxFiles: finalConfig.maxFiles,
231
+ format: fileFormat
232
+ }),
233
+ // Error logs only
234
+ new DailyRotateFile__default.default({
235
+ filename: path__default.default.join(finalConfig.logsDir, "error-%DATE%.log"),
236
+ datePattern: "YYYY-MM-DD",
237
+ level: "error",
238
+ maxSize: finalConfig.maxSize,
239
+ maxFiles: finalConfig.errorMaxFiles,
240
+ format: fileFormat
241
+ })
242
+ ];
243
+ return winston__default.default.createLogger({
244
+ level: finalConfig.level,
245
+ levels,
246
+ format: fileFormat,
247
+ transports,
248
+ exitOnError: false
249
+ });
250
+ };
251
+ var logger = createLogger();
252
+ var createMorganStream = (loggerInstance) => ({
253
+ write: (message) => {
254
+ loggerInstance.http(message.trim());
255
+ }
256
+ });
257
+ var stream = createMorganStream(logger);
258
+ var serializeMeta = (meta) => {
259
+ if (meta === void 0 || meta === null) return "";
260
+ if (meta instanceof Error) {
261
+ return JSON.stringify({ message: meta.message, stack: meta.stack }, null, 2);
262
+ }
263
+ try {
264
+ return JSON.stringify(meta, null, 2);
265
+ } catch {
266
+ return String(meta);
267
+ }
268
+ };
269
+ var simpleLogger = {
270
+ info: (message, meta) => {
271
+ console.log(`[INFO] ${message}`, serializeMeta(meta));
272
+ },
273
+ error: (message, meta) => {
274
+ console.error(`[ERROR] ${message}`, serializeMeta(meta));
275
+ },
276
+ warn: (message, meta) => {
277
+ console.warn(`[WARN] ${message}`, serializeMeta(meta));
278
+ },
279
+ debug: (message, meta) => {
280
+ console.debug(`[DEBUG] ${message}`, serializeMeta(meta));
281
+ }
282
+ };
283
+ var defaultOptions = {
284
+ maxPoolSize: process.env.NODE_ENV === "production" ? 50 : 10,
285
+ minPoolSize: process.env.NODE_ENV === "production" ? 10 : 5,
286
+ socketTimeoutMS: 45e3,
287
+ serverSelectionTimeoutMS: 1e4,
288
+ maxIdleTimeMS: 1e4,
289
+ retryWrites: true,
290
+ retryReads: true,
291
+ w: "majority"
292
+ };
293
+ var connectDB = async (mongoUri, options = {}, logger2) => {
294
+ if (mongoose__default.default.connection.readyState === 1) {
295
+ logger2?.info("Database already connected, reusing connection");
296
+ return mongoose__default.default;
297
+ }
298
+ const finalOptions = { ...defaultOptions, ...options };
299
+ try {
300
+ await mongoose__default.default.connect(mongoUri, finalOptions);
301
+ logger2?.info("MongoDB connected successfully");
302
+ mongoose__default.default.connection.on("error", (err) => {
303
+ logger2?.error("MongoDB connection error", err);
304
+ });
305
+ mongoose__default.default.connection.on("disconnected", () => {
306
+ logger2?.info("MongoDB disconnected");
307
+ });
308
+ mongoose__default.default.connection.on("reconnected", () => {
309
+ logger2?.info("MongoDB reconnected");
310
+ });
311
+ return mongoose__default.default;
312
+ } catch (error) {
313
+ const errorMessage = error instanceof Error ? error.message : String(error);
314
+ logger2?.error("MongoDB connection failed", { error: errorMessage });
315
+ throw error;
316
+ }
317
+ };
318
+ var disconnectDB = async (logger2) => {
319
+ try {
320
+ await mongoose__default.default.disconnect();
321
+ logger2?.info("MongoDB disconnected successfully");
322
+ } catch (error) {
323
+ logger2?.error("Error disconnecting from MongoDB", error);
324
+ throw error;
325
+ }
326
+ };
327
+ var getConnectionStatus = () => {
328
+ const states = {
329
+ 0: "disconnected",
330
+ 1: "connected",
331
+ 2: "connecting",
332
+ 3: "disconnecting"
333
+ };
334
+ return states[mongoose__default.default.connection.readyState] || "unknown";
335
+ };
336
+ var authenticateJWT = (secretKey) => {
337
+ return (req, res, next) => {
338
+ const authHeader = req.headers.authorization;
339
+ if (!authHeader || !authHeader.startsWith("Bearer ")) {
340
+ unauthorizedResponse(res, "Authorization header missing or malformed");
341
+ return;
342
+ }
343
+ const token = authHeader.split(" ")[1];
344
+ try {
345
+ const decoded = jwt__default.default.verify(token, secretKey);
346
+ req.userId = decoded.userId;
347
+ req.organizationId = decoded.organizationId;
348
+ req.user = decoded;
349
+ if (!decoded.userId) {
350
+ unauthorizedResponse(res, "User ID not found in token");
351
+ return;
352
+ }
353
+ next();
354
+ } catch (err) {
355
+ if (err instanceof jwt__default.default.TokenExpiredError) {
356
+ unauthorizedResponse(res, "Token has expired");
357
+ return;
358
+ }
359
+ if (err instanceof jwt__default.default.JsonWebTokenError) {
360
+ forbiddenResponse(res, "Invalid token");
361
+ return;
362
+ }
363
+ unauthorizedResponse(res, "Token validation failed");
364
+ }
365
+ };
366
+ };
367
+ var optionalAuthenticateJWT = (secretKey) => {
368
+ return (req, _res, next) => {
369
+ const authHeader = req.headers.authorization;
370
+ if (!authHeader || !authHeader.startsWith("Bearer ")) {
371
+ next();
372
+ return;
373
+ }
374
+ const token = authHeader.split(" ")[1];
375
+ try {
376
+ const decoded = jwt__default.default.verify(token, secretKey);
377
+ req.userId = decoded.userId;
378
+ req.organizationId = decoded.organizationId;
379
+ req.user = decoded;
380
+ } catch {
381
+ }
382
+ next();
383
+ };
384
+ };
385
+ var authenticateApiKey = (validateKeyFn) => {
386
+ return async (req, res, next) => {
387
+ try {
388
+ const apiKey = req.headers["x-api-key"];
389
+ if (!apiKey) {
390
+ unauthorizedResponse(res, "API key is required. Please provide x-api-key header");
391
+ return;
392
+ }
393
+ const validation = await validateKeyFn(apiKey);
394
+ if (!validation.valid) {
395
+ unauthorizedResponse(res, "Invalid or inactive API key");
396
+ return;
397
+ }
398
+ if (validation.organizationId) {
399
+ req.organizationId = validation.organizationId;
400
+ }
401
+ if (validation.keyId && validation.keyName) {
402
+ req.apiKey = {
403
+ _id: validation.keyId,
404
+ name: validation.keyName
405
+ };
406
+ }
407
+ next();
408
+ } catch {
409
+ unauthorizedResponse(res, "API key validation failed");
410
+ }
411
+ };
412
+ };
413
+ var extractOrganization = (req, _res, next) => {
414
+ const orgId = req.headers["x-organization-id"];
415
+ if (orgId) {
416
+ req.organizationId = orgId;
417
+ }
418
+ next();
419
+ };
420
+ var requireOrganization = (req, res, next) => {
421
+ if (!req.organizationId) {
422
+ unauthorizedResponse(res, "Organization ID is required");
423
+ return;
424
+ }
425
+ next();
426
+ };
427
+
428
+ // src/server/utils/filter-builder.ts
429
+ var buildFilter = (options) => {
430
+ const {
431
+ organizationId,
432
+ search,
433
+ searchFields = [],
434
+ dateField = "createdAt",
435
+ startDate,
436
+ endDate,
437
+ status,
438
+ isActive,
439
+ ...additionalFilters
440
+ } = options;
441
+ const filter = {};
442
+ if (organizationId) {
443
+ filter.organizationId = organizationId;
444
+ }
445
+ if (search && search.trim().length >= 2 && searchFields.length > 0) {
446
+ const searchRegex = new RegExp(search.trim(), "i");
447
+ filter.$or = searchFields.map((field) => ({ [field]: searchRegex }));
448
+ }
449
+ if (startDate || endDate) {
450
+ filter[dateField] = {};
451
+ if (startDate) {
452
+ filter[dateField].$gte = new Date(startDate);
453
+ }
454
+ if (endDate) {
455
+ filter[dateField].$lte = new Date(endDate);
456
+ }
457
+ }
458
+ if (status !== void 0) {
459
+ filter.status = status;
460
+ }
461
+ if (isActive !== void 0) {
462
+ filter.isActive = isActive;
463
+ }
464
+ Object.entries(additionalFilters).forEach(([key, value]) => {
465
+ if (value !== void 0 && value !== null && value !== "") {
466
+ filter[key] = value;
467
+ }
468
+ });
469
+ return filter;
470
+ };
471
+ var buildPagination = (options) => {
472
+ const { page = 1, limit, defaultLimit = 10, maxLimit = 100 } = options;
473
+ const finalPage = Math.max(1, page);
474
+ const finalLimit = Math.min(maxLimit, Math.max(1, limit || defaultLimit));
475
+ const skip = (finalPage - 1) * finalLimit;
476
+ return {
477
+ skip,
478
+ limit: finalLimit,
479
+ page: finalPage
480
+ };
481
+ };
482
+ var buildPaginationMeta = (total, page, limit) => {
483
+ const totalPages = Math.ceil(total / limit);
484
+ return {
485
+ total,
486
+ page,
487
+ limit,
488
+ totalPages,
489
+ hasNextPage: page < totalPages,
490
+ hasPrevPage: page > 1
491
+ };
492
+ };
493
+
494
+ // src/server/utils/sanitize.ts
495
+ var sanitizeUser = (user, additionalFieldsToRemove = []) => {
496
+ if (!user) return null;
497
+ const fieldsToRemove = ["password", "__v", "_id", ...additionalFieldsToRemove];
498
+ const obj = typeof user.toObject === "function" ? user.toObject() : { ...user };
499
+ fieldsToRemove.forEach((field) => {
500
+ delete obj[field];
501
+ });
502
+ return obj;
503
+ };
504
+ var sanitizeDocument = (doc, fieldsToRemove) => {
505
+ if (!doc) return null;
506
+ const obj = typeof doc.toObject === "function" ? doc.toObject() : { ...doc };
507
+ fieldsToRemove.forEach((field) => {
508
+ delete obj[field];
509
+ });
510
+ return obj;
511
+ };
512
+ var pickFields = (obj, fieldsToPick) => {
513
+ if (!obj) return null;
514
+ const result = {};
515
+ fieldsToPick.forEach((field) => {
516
+ if (field in obj) {
517
+ result[field] = obj[field];
518
+ }
519
+ });
520
+ return result;
521
+ };
522
+ var omitFields = (obj, fieldsToOmit) => {
523
+ if (!obj) return null;
524
+ const result = { ...obj };
525
+ fieldsToOmit.forEach((field) => {
526
+ delete result[field];
527
+ });
528
+ return result;
529
+ };
530
+
531
+ exports.StatusCode = StatusCode;
532
+ exports.StatusMessage = StatusMessage;
533
+ exports.authenticateApiKey = authenticateApiKey;
534
+ exports.authenticateJWT = authenticateJWT;
535
+ exports.badRequestResponse = badRequestResponse;
536
+ exports.buildFilter = buildFilter;
537
+ exports.buildPagination = buildPagination;
538
+ exports.buildPaginationMeta = buildPaginationMeta;
539
+ exports.conflictResponse = conflictResponse;
540
+ exports.connectDB = connectDB;
541
+ exports.createLogger = createLogger;
542
+ exports.createMorganStream = createMorganStream;
543
+ exports.createdResponse = createdResponse;
544
+ exports.disconnectDB = disconnectDB;
545
+ exports.errorResponse = errorResponse;
546
+ exports.extractColumns = extractColumns;
547
+ exports.extractOrganization = extractOrganization;
548
+ exports.forbiddenResponse = forbiddenResponse;
549
+ exports.getConnectionStatus = getConnectionStatus;
550
+ exports.logger = logger;
551
+ exports.noContentResponse = noContentResponse;
552
+ exports.notFoundResponse = notFoundResponse;
553
+ exports.omitFields = omitFields;
554
+ exports.optionalAuthenticateJWT = optionalAuthenticateJWT;
555
+ exports.pickFields = pickFields;
556
+ exports.rateLimitResponse = rateLimitResponse;
557
+ exports.requireOrganization = requireOrganization;
558
+ exports.sanitizeDocument = sanitizeDocument;
559
+ exports.sanitizeUser = sanitizeUser;
560
+ exports.simpleLogger = simpleLogger;
561
+ exports.statusCode = statusCode;
562
+ exports.statusMessage = statusMessage;
563
+ exports.stream = stream;
564
+ exports.successResponse = successResponse;
565
+ exports.successResponseArr = successResponseArr;
566
+ exports.unauthorizedResponse = unauthorizedResponse;
567
+ exports.validationErrorResponse = validationErrorResponse;
568
+ //# sourceMappingURL=index.js.map
569
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/server/enums/status.ts","../../src/server/response/response-object.ts","../../src/server/logger/winston-logger.ts","../../src/server/db/mongoose-connect.ts","../../src/server/middleware/auth.middleware.ts","../../src/server/utils/filter-builder.ts","../../src/server/utils/sanitize.ts"],"names":["StatusCode","StatusMessage","winston","DailyRotateFile","path","logger","mongoose","jwt"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * HTTP Status Codes\r\n * Standard HTTP status codes used across all projects\r\n */\r\nexport enum StatusCode {\r\n // Success\r\n SUCCESS = 200,\r\n CREATED = 201,\r\n ACCEPTED = 202,\r\n NO_CONTENT = 204,\r\n\r\n // Client Errors\r\n BAD_REQUEST = 400,\r\n UNAUTHORIZED = 401,\r\n FORBIDDEN = 403,\r\n NOT_FOUND = 404,\r\n CONFLICT = 409,\r\n UNPROCESSABLE_ENTITY = 422,\r\n TOO_MANY_REQUESTS = 429,\r\n\r\n // Server Errors\r\n INTERNAL_ERROR = 500,\r\n NOT_IMPLEMENTED = 501,\r\n BAD_GATEWAY = 502,\r\n SERVICE_UNAVAILABLE = 503,\r\n}\r\n\r\n/**\r\n * Status Messages\r\n * Human-readable status messages\r\n */\r\nexport enum StatusMessage {\r\n SUCCESS = 'success',\r\n CREATED = 'created',\r\n ACCEPTED = 'accepted',\r\n NO_CONTENT = 'no-data-found',\r\n BAD_REQUEST = 'bad-request',\r\n UNAUTHORIZED = 'unauthorized',\r\n FORBIDDEN = 'forbidden',\r\n NOT_FOUND = 'not-found',\r\n CONFLICT = 'conflict',\r\n UNPROCESSABLE_ENTITY = 'validation-error',\r\n TOO_MANY_REQUESTS = 'rate-limit-exceeded',\r\n INTERNAL_ERROR = 'error',\r\n NOT_IMPLEMENTED = 'not-implemented',\r\n BAD_GATEWAY = 'bad-gateway',\r\n SERVICE_UNAVAILABLE = 'service-unavailable',\r\n}\r\n\r\n// Legacy aliases for backward compatibility\r\nexport const statusCode = StatusCode;\r\nexport const statusMessage = StatusMessage;\r\n\r\nexport default {\r\n StatusCode,\r\n StatusMessage,\r\n statusCode,\r\n statusMessage,\r\n};\r\n","import type { Response } from 'express';\r\nimport { StatusCode, StatusMessage } from '../enums/status';\r\n\r\n/**\r\n * Standard API Response Interface\r\n */\r\nexport interface ApiResponse<T = unknown> {\r\n message: string;\r\n data: T | null;\r\n status: string;\r\n statusCode: number;\r\n paginationData?: PaginationData;\r\n columns?: ColumnMetadata[];\r\n}\r\n\r\n/**\r\n * Pagination Data Interface\r\n */\r\nexport interface PaginationData {\r\n total?: number;\r\n page?: number;\r\n limit?: number;\r\n totalPages?: number;\r\n hasNextPage?: boolean;\r\n hasPrevPage?: boolean;\r\n}\r\n\r\n/**\r\n * Column Metadata Interface (for dynamic tables)\r\n */\r\nexport interface ColumnMetadata {\r\n name: string;\r\n datatype: string;\r\n required: boolean;\r\n}\r\n\r\n/**\r\n * Extract column metadata from data array\r\n */\r\nexport const extractColumns = <T extends Record<string, unknown>>(\r\n data: T[]\r\n): ColumnMetadata[] => {\r\n if (!Array.isArray(data) || data.length === 0) {\r\n return [];\r\n }\r\n\r\n const sample = data[0];\r\n return Object.entries(sample).map(([key, value]) => {\r\n let datatype: string = typeof value;\r\n\r\n if (value === null) {\r\n datatype = 'null';\r\n } else if (Array.isArray(value)) {\r\n datatype = 'array';\r\n } else if (value instanceof Date) {\r\n datatype = 'date';\r\n } else if (typeof value === 'object') {\r\n datatype = 'object';\r\n }\r\n\r\n return {\r\n name: key,\r\n datatype,\r\n required: value !== null && value !== undefined,\r\n };\r\n });\r\n};\r\n\r\n/**\r\n * Success Response (200)\r\n */\r\nexport const successResponse = <T>(\r\n res: Response,\r\n data: T,\r\n message = 'Operation successful'\r\n): Response => {\r\n return res.status(StatusCode.SUCCESS).json({\r\n message,\r\n data,\r\n status: StatusMessage.SUCCESS,\r\n statusCode: StatusCode.SUCCESS,\r\n });\r\n};\r\n\r\n/**\r\n * Success Response with Array & Pagination (200)\r\n */\r\nexport const successResponseArr = <T>(\r\n res: Response,\r\n data: T[],\r\n paginationData: PaginationData = {},\r\n message = 'Operation successful'\r\n): Response => {\r\n return res.status(StatusCode.SUCCESS).json({\r\n message,\r\n data,\r\n columns: extractColumns(data as Record<string, unknown>[]),\r\n paginationData,\r\n status: StatusMessage.SUCCESS,\r\n statusCode: StatusCode.SUCCESS,\r\n });\r\n};\r\n\r\n/**\r\n * Created Response (201)\r\n */\r\nexport const createdResponse = <T>(\r\n res: Response,\r\n data: T,\r\n message = 'Resource created successfully'\r\n): Response => {\r\n return res.status(StatusCode.CREATED).json({\r\n message,\r\n data,\r\n status: StatusMessage.CREATED,\r\n statusCode: StatusCode.CREATED,\r\n });\r\n};\r\n\r\n/**\r\n * No Content Response (204 as 200 with message)\r\n */\r\nexport const noContentResponse = <T = null>(\r\n res: Response,\r\n data: T = null as T,\r\n message = 'No data found'\r\n): Response => {\r\n return res.status(StatusCode.SUCCESS).json({\r\n message,\r\n data,\r\n status: StatusMessage.NO_CONTENT,\r\n statusCode: StatusCode.NO_CONTENT,\r\n });\r\n};\r\n\r\n/**\r\n * Bad Request Response (400)\r\n */\r\nexport const badRequestResponse = (\r\n res: Response,\r\n message = 'Bad request',\r\n errors: unknown = null\r\n): Response => {\r\n return res.status(StatusCode.BAD_REQUEST).json({\r\n message,\r\n data: errors,\r\n status: StatusMessage.BAD_REQUEST,\r\n statusCode: StatusCode.BAD_REQUEST,\r\n });\r\n};\r\n\r\n/**\r\n * Unauthorized Response (401)\r\n */\r\nexport const unauthorizedResponse = (\r\n res: Response,\r\n message = 'Unauthorized access'\r\n): Response => {\r\n return res.status(StatusCode.UNAUTHORIZED).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.UNAUTHORIZED,\r\n statusCode: StatusCode.UNAUTHORIZED,\r\n });\r\n};\r\n\r\n/**\r\n * Forbidden Response (403)\r\n */\r\nexport const forbiddenResponse = (\r\n res: Response,\r\n message = 'Access forbidden'\r\n): Response => {\r\n return res.status(StatusCode.FORBIDDEN).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.FORBIDDEN,\r\n statusCode: StatusCode.FORBIDDEN,\r\n });\r\n};\r\n\r\n/**\r\n * Not Found Response (404)\r\n */\r\nexport const notFoundResponse = (\r\n res: Response,\r\n message = 'Resource not found'\r\n): Response => {\r\n return res.status(StatusCode.NOT_FOUND).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.NOT_FOUND,\r\n statusCode: StatusCode.NOT_FOUND,\r\n });\r\n};\r\n\r\n/**\r\n * Conflict Response (409)\r\n */\r\nexport const conflictResponse = (\r\n res: Response,\r\n message = 'Resource conflict'\r\n): Response => {\r\n return res.status(StatusCode.CONFLICT).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.CONFLICT,\r\n statusCode: StatusCode.CONFLICT,\r\n });\r\n};\r\n\r\n/**\r\n * Validation Error Response (422)\r\n */\r\nexport const validationErrorResponse = (\r\n res: Response,\r\n errors: unknown,\r\n message = 'Validation failed'\r\n): Response => {\r\n return res.status(StatusCode.UNPROCESSABLE_ENTITY).json({\r\n message,\r\n data: errors,\r\n status: StatusMessage.UNPROCESSABLE_ENTITY,\r\n statusCode: StatusCode.UNPROCESSABLE_ENTITY,\r\n });\r\n};\r\n\r\n/**\r\n * Error Response (500)\r\n */\r\nexport const errorResponse = (\r\n res: Response,\r\n error: unknown = null,\r\n message = 'Something went wrong'\r\n): Response => {\r\n return res.status(StatusCode.INTERNAL_ERROR).json({\r\n message,\r\n data: error,\r\n status: StatusMessage.INTERNAL_ERROR,\r\n statusCode: StatusCode.INTERNAL_ERROR,\r\n });\r\n};\r\n\r\n/**\r\n * Rate Limit Response (429)\r\n */\r\nexport const rateLimitResponse = (\r\n res: Response,\r\n message = 'Too many requests, please try again later'\r\n): Response => {\r\n return res.status(StatusCode.TOO_MANY_REQUESTS).json({\r\n message,\r\n data: null,\r\n status: StatusMessage.TOO_MANY_REQUESTS,\r\n statusCode: StatusCode.TOO_MANY_REQUESTS,\r\n });\r\n};\r\n\r\nexport default {\r\n successResponse,\r\n successResponseArr,\r\n createdResponse,\r\n noContentResponse,\r\n badRequestResponse,\r\n unauthorizedResponse,\r\n forbiddenResponse,\r\n notFoundResponse,\r\n conflictResponse,\r\n validationErrorResponse,\r\n errorResponse,\r\n rateLimitResponse,\r\n extractColumns,\r\n};\r\n","import winston from 'winston';\r\nimport DailyRotateFile from 'winston-daily-rotate-file';\r\nimport path from 'path';\r\n\r\n/**\r\n * Logger Configuration Options\r\n */\r\nexport interface LoggerConfig {\r\n level?: string;\r\n logsDir?: string;\r\n maxSize?: string;\r\n maxFiles?: string;\r\n errorMaxFiles?: string;\r\n}\r\n\r\n/**\r\n * Default logger configuration\r\n */\r\nconst defaultConfig: LoggerConfig = {\r\n level: process.env.LOG_LEVEL || 'info',\r\n logsDir: 'logs',\r\n maxSize: '20m',\r\n maxFiles: '14d',\r\n errorMaxFiles: '30d',\r\n};\r\n\r\n// Define log levels\r\nconst levels = {\r\n error: 0,\r\n warn: 1,\r\n info: 2,\r\n http: 3,\r\n debug: 4,\r\n};\r\n\r\n// Define colors for each level\r\nconst colors = {\r\n error: 'red',\r\n warn: 'yellow',\r\n info: 'green',\r\n http: 'magenta',\r\n debug: 'blue',\r\n};\r\n\r\nwinston.addColors(colors);\r\n\r\n// JSON format for file logs\r\nconst fileFormat = winston.format.combine(\r\n winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),\r\n winston.format.errors({ stack: true }),\r\n winston.format.splat(),\r\n winston.format.json()\r\n);\r\n\r\n// Colorized format for console\r\nconst consoleFormat = winston.format.combine(\r\n winston.format.colorize({ all: true }),\r\n winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),\r\n winston.format.printf((info) => {\r\n const timestamp = info.timestamp as string | undefined;\r\n const level = info.level as string;\r\n const message = info.message as string;\r\n const stack = info.stack as string | undefined;\r\n return `${timestamp} [${level}]: ${message}${stack ? '\\n' + stack : ''}`;\r\n })\r\n);\r\n\r\n/**\r\n * Create a configured Winston logger instance\r\n */\r\nexport const createLogger = (config: LoggerConfig = {}) => {\r\n const finalConfig = { ...defaultConfig, ...config };\r\n\r\n const transports: winston.transport[] = [\r\n // Console transport\r\n new winston.transports.Console({\r\n format: consoleFormat,\r\n }),\r\n\r\n // Combined logs (all levels)\r\n new DailyRotateFile({\r\n filename: path.join(finalConfig.logsDir!, 'combined-%DATE%.log'),\r\n datePattern: 'YYYY-MM-DD',\r\n maxSize: finalConfig.maxSize,\r\n maxFiles: finalConfig.maxFiles,\r\n format: fileFormat,\r\n }),\r\n\r\n // Error logs only\r\n new DailyRotateFile({\r\n filename: path.join(finalConfig.logsDir!, 'error-%DATE%.log'),\r\n datePattern: 'YYYY-MM-DD',\r\n level: 'error',\r\n maxSize: finalConfig.maxSize,\r\n maxFiles: finalConfig.errorMaxFiles,\r\n format: fileFormat,\r\n }),\r\n ];\r\n\r\n return winston.createLogger({\r\n level: finalConfig.level,\r\n levels,\r\n format: fileFormat,\r\n transports,\r\n exitOnError: false,\r\n });\r\n};\r\n\r\n// Default logger instance\r\nexport const logger = createLogger();\r\n\r\n/**\r\n * Create a stream for Morgan HTTP logger\r\n */\r\nexport const createMorganStream = (loggerInstance: winston.Logger) => ({\r\n write: (message: string) => {\r\n loggerInstance.http(message.trim());\r\n },\r\n});\r\n\r\nexport const stream = createMorganStream(logger);\r\n\r\n/**\r\n * Simple logger for development (no file output)\r\n */\r\nconst serializeMeta = (meta: unknown): string => {\r\n if (meta === undefined || meta === null) return '';\r\n if (meta instanceof Error) {\r\n return JSON.stringify({ message: meta.message, stack: meta.stack }, null, 2);\r\n }\r\n try {\r\n return JSON.stringify(meta, null, 2);\r\n } catch {\r\n return String(meta);\r\n }\r\n};\r\n\r\nexport const simpleLogger = {\r\n info: (message: string, meta?: unknown) => {\r\n console.log(`[INFO] ${message}`, serializeMeta(meta));\r\n },\r\n error: (message: string, meta?: unknown) => {\r\n console.error(`[ERROR] ${message}`, serializeMeta(meta));\r\n },\r\n warn: (message: string, meta?: unknown) => {\r\n console.warn(`[WARN] ${message}`, serializeMeta(meta));\r\n },\r\n debug: (message: string, meta?: unknown) => {\r\n console.debug(`[DEBUG] ${message}`, serializeMeta(meta));\r\n },\r\n};\r\n\r\nexport default logger;\r\n","import mongoose, { ConnectOptions } from 'mongoose';\r\n\r\n/**\r\n * Database Connection Options\r\n */\r\nexport interface DbConnectionOptions {\r\n maxPoolSize?: number;\r\n minPoolSize?: number;\r\n socketTimeoutMS?: number;\r\n serverSelectionTimeoutMS?: number;\r\n maxIdleTimeMS?: number;\r\n retryWrites?: boolean;\r\n retryReads?: boolean;\r\n w?: 'majority' | number;\r\n}\r\n\r\n/**\r\n * Default connection options\r\n */\r\nconst defaultOptions: DbConnectionOptions = {\r\n maxPoolSize: process.env.NODE_ENV === 'production' ? 50 : 10,\r\n minPoolSize: process.env.NODE_ENV === 'production' ? 10 : 5,\r\n socketTimeoutMS: 45000,\r\n serverSelectionTimeoutMS: 10000,\r\n maxIdleTimeMS: 10000,\r\n retryWrites: true,\r\n retryReads: true,\r\n w: 'majority',\r\n};\r\n\r\n/**\r\n * Connect to MongoDB with mongoose\r\n * @param mongoUri - MongoDB connection string\r\n * @param options - Connection options\r\n * @param logger - Optional logger instance\r\n */\r\nexport const connectDB = async (\r\n mongoUri: string,\r\n options: DbConnectionOptions = {},\r\n logger?: { info: (msg: string, meta?: unknown) => void; error: (msg: string, meta?: unknown) => void }\r\n): Promise<typeof mongoose> => {\r\n // Check if already connected\r\n if (mongoose.connection.readyState === 1) {\r\n logger?.info('Database already connected, reusing connection');\r\n return mongoose;\r\n }\r\n\r\n const finalOptions: ConnectOptions = { ...defaultOptions, ...options };\r\n\r\n try {\r\n await mongoose.connect(mongoUri, finalOptions);\r\n logger?.info('MongoDB connected successfully');\r\n\r\n // Handle connection events\r\n mongoose.connection.on('error', (err: Error) => {\r\n logger?.error('MongoDB connection error', err);\r\n });\r\n\r\n mongoose.connection.on('disconnected', () => {\r\n logger?.info('MongoDB disconnected');\r\n });\r\n\r\n mongoose.connection.on('reconnected', () => {\r\n logger?.info('MongoDB reconnected');\r\n });\r\n\r\n return mongoose;\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : String(error);\r\n logger?.error('MongoDB connection failed', { error: errorMessage });\r\n throw error;\r\n }\r\n};\r\n\r\n/**\r\n * Disconnect from MongoDB\r\n */\r\nexport const disconnectDB = async (\r\n logger?: { info: (msg: string) => void; error: (msg: string, meta?: unknown) => void }\r\n): Promise<void> => {\r\n try {\r\n await mongoose.disconnect();\r\n logger?.info('MongoDB disconnected successfully');\r\n } catch (error) {\r\n logger?.error('Error disconnecting from MongoDB', error);\r\n throw error;\r\n }\r\n};\r\n\r\n/**\r\n * Get connection status\r\n */\r\nexport const getConnectionStatus = (): string => {\r\n const states: Record<number, string> = {\r\n 0: 'disconnected',\r\n 1: 'connected',\r\n 2: 'connecting',\r\n 3: 'disconnecting',\r\n };\r\n return states[mongoose.connection.readyState] || 'unknown';\r\n};\r\n\r\nexport default {\r\n connectDB,\r\n disconnectDB,\r\n getConnectionStatus,\r\n};\r\n","import type { Request, Response, NextFunction } from 'express';\r\nimport jwt from 'jsonwebtoken';\r\nimport { unauthorizedResponse, forbiddenResponse } from '../response/response-object';\r\n\r\n/**\r\n * Extended Request with auth information\r\n */\r\nexport interface AuthRequest extends Request {\r\n userId?: string;\r\n organizationId?: string;\r\n apiKey?: { _id: string; name: string };\r\n user?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * JWT Payload Interface\r\n */\r\nexport interface JWTPayload {\r\n userId: string;\r\n organizationId?: string;\r\n email?: string;\r\n role?: string;\r\n [key: string]: unknown;\r\n}\r\n\r\n/**\r\n * JWT Authentication Middleware\r\n * Validates Bearer token from Authorization header\r\n */\r\nexport const authenticateJWT = (secretKey: string) => {\r\n return (req: AuthRequest, res: Response, next: NextFunction): void => {\r\n const authHeader = req.headers.authorization;\r\n\r\n if (!authHeader || !authHeader.startsWith('Bearer ')) {\r\n unauthorizedResponse(res, 'Authorization header missing or malformed');\r\n return;\r\n }\r\n\r\n const token = authHeader.split(' ')[1];\r\n\r\n try {\r\n const decoded = jwt.verify(token, secretKey) as JWTPayload;\r\n\r\n req.userId = decoded.userId;\r\n req.organizationId = decoded.organizationId;\r\n req.user = decoded as Record<string, unknown>;\r\n\r\n if (!decoded.userId) {\r\n unauthorizedResponse(res, 'User ID not found in token');\r\n return;\r\n }\r\n\r\n next();\r\n } catch (err) {\r\n if (err instanceof jwt.TokenExpiredError) {\r\n unauthorizedResponse(res, 'Token has expired');\r\n return;\r\n }\r\n if (err instanceof jwt.JsonWebTokenError) {\r\n forbiddenResponse(res, 'Invalid token');\r\n return;\r\n }\r\n unauthorizedResponse(res, 'Token validation failed');\r\n }\r\n };\r\n};\r\n\r\n/**\r\n * Optional JWT Authentication Middleware\r\n * Validates token if present, but doesn't require it\r\n */\r\nexport const optionalAuthenticateJWT = (secretKey: string) => {\r\n return (req: AuthRequest, _res: Response, next: NextFunction): void => {\r\n const authHeader = req.headers.authorization;\r\n\r\n if (!authHeader || !authHeader.startsWith('Bearer ')) {\r\n next();\r\n return;\r\n }\r\n\r\n const token = authHeader.split(' ')[1];\r\n\r\n try {\r\n const decoded = jwt.verify(token, secretKey) as JWTPayload;\r\n req.userId = decoded.userId;\r\n req.organizationId = decoded.organizationId;\r\n req.user = decoded as Record<string, unknown>;\r\n } catch {\r\n // Token invalid, but continue without auth\r\n }\r\n\r\n next();\r\n };\r\n};\r\n\r\n/**\r\n * API Key Authentication Middleware\r\n * Validates x-api-key header\r\n */\r\nexport const authenticateApiKey = (\r\n validateKeyFn: (key: string) => Promise<{\r\n valid: boolean;\r\n organizationId?: string;\r\n keyId?: string;\r\n keyName?: string;\r\n }>\r\n) => {\r\n return async (req: AuthRequest, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n const apiKey = req.headers['x-api-key'] as string;\r\n\r\n if (!apiKey) {\r\n unauthorizedResponse(res, 'API key is required. Please provide x-api-key header');\r\n return;\r\n }\r\n\r\n const validation = await validateKeyFn(apiKey);\r\n\r\n if (!validation.valid) {\r\n unauthorizedResponse(res, 'Invalid or inactive API key');\r\n return;\r\n }\r\n\r\n if (validation.organizationId) {\r\n req.organizationId = validation.organizationId;\r\n }\r\n if (validation.keyId && validation.keyName) {\r\n req.apiKey = {\r\n _id: validation.keyId,\r\n name: validation.keyName,\r\n };\r\n }\r\n\r\n next();\r\n } catch {\r\n unauthorizedResponse(res, 'API key validation failed');\r\n }\r\n };\r\n};\r\n\r\n/**\r\n * Organization Header Middleware\r\n * Extracts organization ID from x-organization-id header\r\n */\r\nexport const extractOrganization = (req: AuthRequest, _res: Response, next: NextFunction): void => {\r\n const orgId = req.headers['x-organization-id'] as string;\r\n\r\n if (orgId) {\r\n req.organizationId = orgId;\r\n }\r\n\r\n next();\r\n};\r\n\r\n/**\r\n * Require Organization Middleware\r\n * Ensures organizationId is present in request\r\n */\r\nexport const requireOrganization = (req: AuthRequest, res: Response, next: NextFunction): void => {\r\n if (!req.organizationId) {\r\n unauthorizedResponse(res, 'Organization ID is required');\r\n return;\r\n }\r\n next();\r\n};\r\n\r\nexport default {\r\n authenticateJWT,\r\n optionalAuthenticateJWT,\r\n authenticateApiKey,\r\n extractOrganization,\r\n requireOrganization,\r\n};\r\n","/**\r\n * Filter Builder Options\r\n */\r\nexport interface FilterOptions {\r\n organizationId?: string;\r\n search?: string;\r\n searchFields?: string[];\r\n dateField?: string;\r\n startDate?: string;\r\n endDate?: string;\r\n status?: string;\r\n isActive?: boolean;\r\n [key: string]: unknown;\r\n}\r\n\r\n/**\r\n * Pagination Options\r\n */\r\nexport interface PaginationOptions {\r\n page?: number;\r\n limit?: number;\r\n defaultLimit?: number;\r\n maxLimit?: number;\r\n}\r\n\r\n/**\r\n * Pagination Result\r\n */\r\nexport interface PaginationResult {\r\n skip: number;\r\n limit: number;\r\n page: number;\r\n}\r\n\r\n/**\r\n * Build MongoDB filter query dynamically\r\n */\r\nexport const buildFilter = (options: FilterOptions): Record<string, unknown> => {\r\n const {\r\n organizationId,\r\n search,\r\n searchFields = [],\r\n dateField = 'createdAt',\r\n startDate,\r\n endDate,\r\n status,\r\n isActive,\r\n ...additionalFilters\r\n } = options;\r\n\r\n const filter: Record<string, unknown> = {};\r\n\r\n // Add organizationId if provided\r\n if (organizationId) {\r\n filter.organizationId = organizationId;\r\n }\r\n\r\n // Handle text search with regex (min 2 characters)\r\n if (search && search.trim().length >= 2 && searchFields.length > 0) {\r\n const searchRegex = new RegExp(search.trim(), 'i');\r\n filter.$or = searchFields.map((field) => ({ [field]: searchRegex }));\r\n }\r\n\r\n // Handle date range filtering\r\n if (startDate || endDate) {\r\n filter[dateField] = {};\r\n if (startDate) {\r\n (filter[dateField] as Record<string, unknown>).$gte = new Date(startDate);\r\n }\r\n if (endDate) {\r\n (filter[dateField] as Record<string, unknown>).$lte = new Date(endDate);\r\n }\r\n }\r\n\r\n // Handle status filter\r\n if (status !== undefined) {\r\n filter.status = status;\r\n }\r\n\r\n // Handle isActive filter\r\n if (isActive !== undefined) {\r\n filter.isActive = isActive;\r\n }\r\n\r\n // Add any additional filters\r\n Object.entries(additionalFilters).forEach(([key, value]) => {\r\n if (value !== undefined && value !== null && value !== '') {\r\n filter[key] = value;\r\n }\r\n });\r\n\r\n return filter;\r\n};\r\n\r\n/**\r\n * Calculate pagination values\r\n */\r\nexport const buildPagination = (options: PaginationOptions): PaginationResult => {\r\n const { page = 1, limit, defaultLimit = 10, maxLimit = 100 } = options;\r\n\r\n const finalPage = Math.max(1, page);\r\n const finalLimit = Math.min(maxLimit, Math.max(1, limit || defaultLimit));\r\n const skip = (finalPage - 1) * finalLimit;\r\n\r\n return {\r\n skip,\r\n limit: finalLimit,\r\n page: finalPage,\r\n };\r\n};\r\n\r\n/**\r\n * Calculate pagination metadata for response\r\n */\r\nexport const buildPaginationMeta = (\r\n total: number,\r\n page: number,\r\n limit: number\r\n): {\r\n total: number;\r\n page: number;\r\n limit: number;\r\n totalPages: number;\r\n hasNextPage: boolean;\r\n hasPrevPage: boolean;\r\n} => {\r\n const totalPages = Math.ceil(total / limit);\r\n\r\n return {\r\n total,\r\n page,\r\n limit,\r\n totalPages,\r\n hasNextPage: page < totalPages,\r\n hasPrevPage: page > 1,\r\n };\r\n};\r\n\r\nexport default {\r\n buildFilter,\r\n buildPagination,\r\n buildPaginationMeta,\r\n};\r\n","/**\r\n * Sanitize user object by removing sensitive fields\r\n */\r\nexport const sanitizeUser = <T extends Record<string, unknown>>(\r\n user: T | null | undefined,\r\n additionalFieldsToRemove: string[] = []\r\n): Omit<T, 'password' | '__v' | '_id'> | null => {\r\n if (!user) return null;\r\n\r\n const fieldsToRemove = ['password', '__v', '_id', ...additionalFieldsToRemove];\r\n\r\n // Handle mongoose documents\r\n const obj = typeof (user as any).toObject === 'function' \r\n ? (user as any).toObject() \r\n : { ...user };\r\n\r\n fieldsToRemove.forEach((field) => {\r\n delete obj[field];\r\n });\r\n\r\n return obj;\r\n};\r\n\r\n/**\r\n * Sanitize document by removing specified fields\r\n */\r\nexport const sanitizeDocument = <T extends Record<string, unknown>>(\r\n doc: T | null | undefined,\r\n fieldsToRemove: string[]\r\n): Partial<T> | null => {\r\n if (!doc) return null;\r\n\r\n // Handle mongoose documents\r\n const obj = typeof (doc as any).toObject === 'function' \r\n ? (doc as any).toObject() \r\n : { ...doc };\r\n\r\n fieldsToRemove.forEach((field) => {\r\n delete obj[field];\r\n });\r\n\r\n return obj;\r\n};\r\n\r\n/**\r\n * Pick specific fields from an object\r\n */\r\nexport const pickFields = <T extends Record<string, unknown>>(\r\n obj: T | null | undefined,\r\n fieldsToPick: (keyof T)[]\r\n): Partial<T> | null => {\r\n if (!obj) return null;\r\n\r\n const result: Partial<T> = {};\r\n\r\n fieldsToPick.forEach((field) => {\r\n if (field in obj) {\r\n result[field] = obj[field];\r\n }\r\n });\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Omit specific fields from an object\r\n */\r\nexport const omitFields = <T extends Record<string, unknown>, K extends keyof T>(\r\n obj: T | null | undefined,\r\n fieldsToOmit: K[]\r\n): Omit<T, K> | null => {\r\n if (!obj) return null;\r\n\r\n const result = { ...obj };\r\n\r\n fieldsToOmit.forEach((field) => {\r\n delete result[field];\r\n });\r\n\r\n return result as Omit<T, K>;\r\n};\r\n\r\nexport default {\r\n sanitizeUser,\r\n sanitizeDocument,\r\n pickFields,\r\n omitFields,\r\n};\r\n"]}