tsledge-core 0.1.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 (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +100 -0
  3. package/dist/app.d.ts +14 -0
  4. package/dist/app.d.ts.map +1 -0
  5. package/dist/bin/repl.js +1181 -0
  6. package/dist/bin/repl.js.map +7 -0
  7. package/dist/core/http.d.ts +15 -0
  8. package/dist/core/http.d.ts.map +1 -0
  9. package/dist/core/index.d.ts +4 -0
  10. package/dist/core/index.d.ts.map +1 -0
  11. package/dist/core/query-builder.d.ts +96 -0
  12. package/dist/core/query-builder.d.ts.map +1 -0
  13. package/dist/core/types.d.ts +58 -0
  14. package/dist/core/types.d.ts.map +1 -0
  15. package/dist/db/index.d.ts +2 -0
  16. package/dist/db/index.d.ts.map +1 -0
  17. package/dist/db/mongodb.d.ts +6 -0
  18. package/dist/db/mongodb.d.ts.map +1 -0
  19. package/dist/exitCodes.d.ts +4 -0
  20. package/dist/exitCodes.d.ts.map +1 -0
  21. package/dist/fluent-interface/fluent-pattern-handler.d.ts +60 -0
  22. package/dist/fluent-interface/fluent-pattern-handler.d.ts.map +1 -0
  23. package/dist/fluent-interface/index.d.ts +3 -0
  24. package/dist/fluent-interface/index.d.ts.map +1 -0
  25. package/dist/fluent-interface/types.d.ts +26 -0
  26. package/dist/fluent-interface/types.d.ts.map +1 -0
  27. package/dist/index.d.ts +10 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/middleware/authentication/index.d.ts +4 -0
  30. package/dist/middleware/authentication/index.d.ts.map +1 -0
  31. package/dist/middleware/authentication/session.d.ts +63 -0
  32. package/dist/middleware/authentication/session.d.ts.map +1 -0
  33. package/dist/middleware/authentication/types.d.ts +34 -0
  34. package/dist/middleware/authentication/types.d.ts.map +1 -0
  35. package/dist/middleware/authentication/validation.d.ts +64 -0
  36. package/dist/middleware/authentication/validation.d.ts.map +1 -0
  37. package/dist/middleware/file-storage.d.ts +4 -0
  38. package/dist/middleware/file-storage.d.ts.map +1 -0
  39. package/dist/middleware/index.d.ts +5 -0
  40. package/dist/middleware/index.d.ts.map +1 -0
  41. package/dist/middleware/logger.d.ts +4 -0
  42. package/dist/middleware/logger.d.ts.map +1 -0
  43. package/dist/middleware/types.d.ts +2 -0
  44. package/dist/middleware/types.d.ts.map +1 -0
  45. package/dist/models/auth-token-blocklist.d.ts +13 -0
  46. package/dist/models/auth-token-blocklist.d.ts.map +1 -0
  47. package/dist/models/auth-user.d.ts +15 -0
  48. package/dist/models/auth-user.d.ts.map +1 -0
  49. package/dist/models/index.d.ts +3 -0
  50. package/dist/models/index.d.ts.map +1 -0
  51. package/dist/src/index.js +1159 -0
  52. package/dist/src/index.js.map +7 -0
  53. package/dist/tests/main.js +1111 -0
  54. package/dist/tests/main.js.map +7 -0
  55. package/dist/types.d.ts +26 -0
  56. package/dist/types.d.ts.map +1 -0
  57. package/dist/utils/date.d.ts +2 -0
  58. package/dist/utils/date.d.ts.map +1 -0
  59. package/dist/utils/encoding.d.ts +13 -0
  60. package/dist/utils/encoding.d.ts.map +1 -0
  61. package/dist/utils/env.d.ts +9 -0
  62. package/dist/utils/env.d.ts.map +1 -0
  63. package/dist/utils/index.d.ts +6 -0
  64. package/dist/utils/index.d.ts.map +1 -0
  65. package/dist/utils/mongo-relation.d.ts +21 -0
  66. package/dist/utils/mongo-relation.d.ts.map +1 -0
  67. package/dist/utils/validation.d.ts +59 -0
  68. package/dist/utils/validation.d.ts.map +1 -0
  69. package/package.json +76 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/index.ts", "../../src/db/mongodb.ts", "../../src/exitCodes.ts", "../../src/utils/date.ts", "../../src/utils/mongo-relation.ts", "../../src/utils/validation.ts", "../../src/utils/env.ts", "../../src/utils/encoding.ts", "../../src/middleware/file-storage.ts", "../../src/middleware/logger.ts", "../../src/middleware/authentication/session.ts", "../../src/middleware/authentication/validation.ts", "../../src/models/auth-user.ts", "../../src/models/auth-token-blocklist.ts", "../../src/fluent-interface/fluent-pattern-handler.ts", "../../src/fluent-interface/types.ts", "../../src/core/query-builder.ts", "../../src/core/types.ts", "../../src/core/http.ts", "../../src/app.ts", "../../bin/repl.ts"],
4
+ "sourcesContent": ["export * from './db/index';\r\nexport * from './middleware/index';\r\nexport * from './fluent-interface/index';\r\nexport * from './core/index';\r\nexport * from './utils/index';\r\nexport * from './models/index';\r\nexport * from './app';\r\nexport * from './types';\r\nexport * from './exitCodes';", "import mongoose from \"mongoose\";\r\nimport { EXIT_CODE_GENERAL_ERROR, EXIT_CODE_INVALID_CONFIG } from \"../exitCodes\";\r\nimport { getCurrentDateString } from \"../utils\";\r\n\r\n/**\r\n * Connects to MongoDB using Mongoose\r\n * @param uri \r\n */\r\nexport async function connectMongoDB(uri: string) {\r\n if(uri == null || uri == undefined || uri.length == 0) {\r\n console.error(`\uD83D\uDED1 [${getCurrentDateString()}] Error: MongoDB URI is not provided`);\r\n process.exit(EXIT_CODE_INVALID_CONFIG);\r\n }\r\n try {\r\n await mongoose.connect(uri);\r\n console.log(`\u2705 [${getCurrentDateString()}] MongoDB connected`);\r\n } catch (err) {\r\n console.error(`\uD83D\uDED1 [${getCurrentDateString()}] Error: MongoDB connection failed`, err);\r\n process.exit(EXIT_CODE_GENERAL_ERROR);\r\n }\r\n}\r\n", "export const EXIT_CODE_SUCCESS = 0;\r\nexport const EXIT_CODE_GENERAL_ERROR = 1; // An unspecified error occurred\r\nexport const EXIT_CODE_INVALID_CONFIG = 2; // incorrect command-line arguments or syntax error.", "export function getCurrentDateString() {\r\n let date = new Date();\r\n return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;\r\n}\r\n", "import mongoose from 'mongoose';\r\n\r\n/**\r\n * Inserts new relations into the collection, avoiding duplicates based on the compareFunc.\r\n * @param model\r\n * @param relations\r\n * @param compareFunc\r\n * @param validateFunc\r\n * @returns\r\n */\r\nexport function insertCollectionRelations<T = any>(\r\n model: mongoose.Model<T>,\r\n relations: any,\r\n compareFunc: any,\r\n validateFunc: any = undefined\r\n) {\r\n if (relations == undefined) {\r\n return;\r\n }\r\n let relationStack: any[] = [];\r\n for (let relation of relations) {\r\n if (validateFunc) {\r\n relation = validateFunc(relation);\r\n }\r\n let inStack = false;\r\n for (let duplicateRelationCheck of relationStack) {\r\n if (compareFunc(relation, duplicateRelationCheck)) {\r\n inStack = true;\r\n }\r\n }\r\n if (!inStack) {\r\n relationStack.push(relation);\r\n }\r\n }\r\n if (relationStack.length > 0) {\r\n model.insertMany(relationStack);\r\n }\r\n}\r\n\r\n/**\r\n * Merges N:N relations by comparing existing relations with new ones,\r\n * removing obsolete relations and creating new ones.\r\n * @param model Mongoose Model for the relation collection\r\n * @param relationsToMerge Array of relations to merge (can be null/undefined)\r\n * @param match MongoDB match query to find existing relations\r\n * @param compareFunc Function to compare two relations for equality\r\n * @param validateFunc Function to validate and transform relation data\r\n */\r\nexport async function mergeCollectionRelations<T>(\r\n model: mongoose.Model<T>,\r\n relationsToMerge: any[] | null | undefined,\r\n match: Record<string, any>,\r\n compareFunc: (a: any, b: any) => boolean,\r\n validateFunc: (relation: any) => any\r\n): Promise<void> {\r\n // Filter duplicates and validate\r\n const relationStack: any[] = [];\r\n\r\n if (relationsToMerge != null) {\r\n for (const relation of relationsToMerge) {\r\n // extract_dict_by_structure is replaced by direct mongoose model instantiation\r\n // The validateFunc should handle the structure extraction and validation\r\n const validatedRelation = validateFunc(relation);\r\n\r\n if (\r\n !relationStack.some((duplicateRelationCheck) =>\r\n compareFunc(validatedRelation, duplicateRelationCheck)\r\n )\r\n ) {\r\n relationStack.push(validatedRelation);\r\n }\r\n }\r\n }\r\n\r\n if (relationStack.length === 0) {\r\n // Delete all matching relations if no new relations to merge\r\n await model.deleteMany(match);\r\n } else {\r\n // Find existing relations\r\n const existingRels = await model.find(match).lean();\r\n const toRemoveRels: any[] = [];\r\n\r\n // Find relations to remove (exist in DB but not in new stack)\r\n for (const rel of existingRels) {\r\n if (!relationStack.some((relationFromStack) => compareFunc(rel, relationFromStack))) {\r\n toRemoveRels.push(rel);\r\n }\r\n }\r\n\r\n // Find relations to create (in new stack but not in DB)\r\n const toCreateRels: any[] = [];\r\n for (const relationFromStack of relationStack) {\r\n if (!existingRels.some((rel) => compareFunc(rel, relationFromStack))) {\r\n toCreateRels.push(relationFromStack);\r\n }\r\n }\r\n\r\n // Execute operations\r\n if (toCreateRels.length > 0) {\r\n await model.insertMany(toCreateRels);\r\n }\r\n\r\n if (toRemoveRels.length > 0) {\r\n const idsToRemove = toRemoveRels.map((rel) => rel._id);\r\n await model.deleteMany({ _id: { $in: idsToRemove } });\r\n }\r\n }\r\n}\r\n", "/**\r\n * Validates that the input is a non-empty object or array.\r\n * @param value\r\n * @returns boolean\r\n */\r\nexport function isNonEmptyObjectOrArray(value: any): boolean {\r\n return (\r\n value != null &&\r\n value != undefined &&\r\n ((Array.isArray(value) && value.length > 0) ||\r\n (typeof value === 'object' &&\r\n !Array.isArray(value) &&\r\n Object.keys(value as object).length > 0))\r\n );\r\n}\r\n\r\n/**\r\n * Validates a string value, returning it if it's not empty, undefined, or null.\r\n * Returns the fallback value otherwise.\r\n *\r\n * @param value - The value to validate.\r\n * @param fallback - The value to return if validation fails.\r\n * @returns The validated string or the fallback.\r\n */\r\nexport function validateString(value: string | undefined | null, fallback: any = null): string | null | any {\r\n if (\r\n value !== undefined &&\r\n value !== null &&\r\n value !== '' &&\r\n value !== 'undefined' &&\r\n value !== 'null'\r\n ) {\r\n return value;\r\n }\r\n return fallback;\r\n}\r\n\r\n/**\r\n * Merges the properties of object `input` into object `target`.\r\n * @param input The source object whose properties will be merged into `target`.\r\n * @param target The target object that will receive the properties from `input`.\r\n * @param prefix An optional prefix to prepend to each key in the merged object.\r\n * @returns The merged object.\r\n */\r\nexport function mergeObjects<T = any>(input: any, target: any, prefix: string | undefined = undefined): T {\r\n if (input && typeof input === 'object' && !Array.isArray(input)) {\r\n if (target && typeof target === 'object' && !Array.isArray(target)) {\r\n Object.entries(input).forEach(([key, value]) => {\r\n if (value != undefined && value != null) {\r\n if (prefix) {\r\n target[`${prefix}.${key}`] = value;\r\n } else {\r\n target[key] = value;\r\n }\r\n }\r\n });\r\n }\r\n }\r\n return target;\r\n}\r\n\r\n/**\r\n * Parses a list from various formats (array, JSON string, or CSV string) into a standardized array of strings.\r\n * @param list \r\n * @param [delimiter=','] \r\n * @returns \r\n */\r\nexport function parseList(list: any, delimiter = ','): string[] {\r\n if (!list) return [];\r\n if (Array.isArray(list)) return list.map((s: any) => String(s).trim()).filter(Boolean);\r\n if (typeof list === 'string') {\r\n try {\r\n const parsed = JSON.parse(list);\r\n if (Array.isArray(parsed)) return parsed.map((s: any) => String(s).trim()).filter(Boolean);\r\n } catch {}\r\n return list\r\n .split(delimiter)\r\n .map((s) => s.trim())\r\n .filter(Boolean);\r\n }\r\n return [];\r\n}\r\n\r\n/**\r\n * Parses a string into a number, returning null if the parsing fails.\r\n * @param value The value to parse.\r\n * @returns The parsed number or null.\r\n */\r\nexport function parseNumber(value: any): number | null {\r\n if (value === undefined || value === null) return null;\r\n if (typeof value === 'number') {\r\n return Number.isFinite(value) ? value : null;\r\n }\r\n const parsedValue = String(value).trim();\r\n if (\r\n parsedValue === '' ||\r\n parsedValue === 'undefined' ||\r\n parsedValue === 'null'\r\n ) {\r\n return null;\r\n }\r\n if (!/^[-+]?(?:\\d+|\\d*\\.\\d+)$/.test(parsedValue)) {\r\n return null;\r\n }\r\n if (parsedValue.includes('.')) {\r\n return parseFloat(parsedValue);\r\n }\r\n return parseInt(parsedValue, 10);\r\n}\r\n\r\n/**\r\n * Checks if a value is a number within a specified range (inclusive).\r\n * @param value The value to check.\r\n * @param from The lower bound of the range (default: 0).\r\n * @param to The upper bound of the range (default: 1).\r\n * @returns True if the value is a number within the range, false otherwise.\r\n */\r\nexport function isNumberInRange(value: any, from: number = 0, to: number = 1): boolean {\r\n value = parseNumber(value);\r\n if(value == null) {\r\n return false;\r\n }\r\n return !isNaN(value) && value >= from && value <= to;\r\n}\r\n\r\n/**\r\n * Clamps a number to be within a specified range.\r\n * @param value \r\n * @param from \r\n * @param to \r\n * @returns \r\n */\r\nexport function clamp(value: any, from: number = 0, to: number = 1): number {\r\n value = parseNumber(value);\r\n if (value == null) {\r\n return from;\r\n }\r\n if (isNaN(value)) return from;\r\n return Math.min(Math.max(value, from), to);\r\n}\r\n\r\n/**\r\n * Parses a value into a boolean\r\n * @param value The value to parse.\r\n * @returns The parsed boolean\r\n */\r\nexport function parseBoolean(value: any, fallback: boolean = false): boolean {\r\n if (value === undefined || value === null) return fallback;\r\n\r\n if (typeof value === 'boolean') {\r\n return value;\r\n }\r\n\r\n if (typeof value === 'string') {\r\n const parsedValue = value.trim().toLowerCase();\r\n if (parsedValue === 'true' || parsedValue === '1' || parsedValue == 'yes') return true;\r\n return false;\r\n }\r\n\r\n if (typeof value === 'object') {\r\n if (value instanceof Boolean) {\r\n return value.valueOf();\r\n }\r\n return fallback;\r\n }\r\n\r\n if (typeof value === 'number') {\r\n if (value > 0) return true;\r\n }\r\n try {\r\n return Boolean(value.trim().toLowerCase());\r\n } catch {}\r\n return fallback;\r\n}", "export const JwtSecret = process.env.JWT_SECRET || 'secret';\r\nexport const JwtRefreshSecret = process.env.JWT_REFRESH_SECRET || 'refresh_secret';\r\n\r\n/**\r\n * Utility function to check if the application is in debug mode based on the DEBUG environment variable.\r\n * @param func Optional function to execute if debug mode is enabled.\r\n * @returns True if debug mode is enabled, false otherwise.\r\n */\r\nexport function isDebug(func: (() => void) | undefined = undefined): boolean {\r\n const dbg = process.env.DEBUG;\r\n if (dbg !== undefined) {\r\n const v = dbg.toString().trim().toLowerCase();\r\n let validation = v === '1' || v === 'true' || v === 'yes' || v === 'on';\r\n if (validation && func != undefined) {\r\n func();\r\n }\r\n return validation;\r\n }\r\n return false;\r\n}\r\n", "/**\r\n * Encodes any object into a base64 string.\r\n * @param obj The object to encode.\r\n * @returns Encoded string in base64 format.\r\n */\r\nexport function encodeToBase64(obj: any): string {\r\n return btoa(encodeURIComponent(JSON.stringify(obj)));\r\n}\r\n\r\n/**\r\n * Decodes a base64 string back into an object.\r\n * @param str The base64 string to decode.\r\n * @returns Decoded object or undefined if the input string is invalid.\r\n */\r\nexport function decodeFromBase64<T = any>(str: string | null | undefined): T | undefined {\r\n if(str == null || str == undefined) {\r\n return undefined;\r\n }\r\n let decoded = str ? decodeURIComponent(atob(str)) : undefined;\r\n return decoded ? JSON.parse(decoded) : undefined;\r\n}", "import multer from 'multer';\r\nimport path from 'node:path';\r\nimport fs from 'node:fs';\r\n\r\nconst uploadDir = path.resolve(process.cwd(), 'src', 'files');\r\nfs.mkdirSync(uploadDir, { recursive: true });\r\n\r\nconst sanitizeFilename = (name: string): string => name.replace(/[^a-zA-Z0-9._-]/g, '_');\r\n\r\nconst diskStorage = multer.diskStorage({\r\n destination: (_req, _file, next) => next(null, uploadDir),\r\n filename: (_req, file, next) => {\r\n const ext = path.extname(file.originalname);\r\n const base = path.basename(file.originalname, ext);\r\n const safe = sanitizeFilename(base);\r\n const unique = Date.now() + '-' + Math.round(Math.random() * 1e9);\r\n next(null, `${safe}-${unique}${ext}`);\r\n },\r\n});\r\n\r\nconst memoryStorage = multer.memoryStorage();\r\n\r\nexport const diskFileUpload = multer({ storage: diskStorage });\r\nexport const memoryFileUpload = multer({ storage: memoryStorage });\r\n", "import { Request, Response, NextFunction } from 'express';\r\nimport { getCurrentDateString } from '../utils/index';\r\n\r\nexport function requestLogger(req: Request, res: Response, next: NextFunction) {\r\n res.on('finish', () => {\r\n let emoji = '';\r\n if (res.statusCode >= 100 && res.statusCode < 200) emoji = '\uD83D\uDCA1';\r\n else if (res.statusCode >= 200 && res.statusCode < 300) emoji = '\u2705';\r\n else if (res.statusCode >= 300 && res.statusCode < 400) emoji = '\uD83D\uDEA6';\r\n else if (res.statusCode == 401) emoji = '\uD83D\uDD01';\r\n else if (res.statusCode >= 400 && res.statusCode < 500) emoji = '\u26A0\uFE0F';\r\n else if (res.statusCode >= 500) emoji = '\uD83D\uDD25';\r\n\r\n console.log(\r\n `${emoji} [${getCurrentDateString()}] ${req.method} ${req.originalUrl} - ${res.statusCode}`\r\n );\r\n });\r\n next();\r\n}\r\n\r\nexport function errorLogger(err: any, req: any, res: any, next: NextFunction) {\r\n console.error(`\uD83D\uDED1 [${getCurrentDateString()}] Error in ${req.method} ${req.originalUrl}:`, err);\r\n res.status(500).json();\r\n}", "import express, { Request, Response } from 'express';\r\nimport bcrypt from 'bcrypt';\r\nimport { JWTCredentials, AuthUserPayload } from './types';\r\nimport { encodeToBase64, JwtRefreshSecret, JwtSecret, validateString } from '../../utils';\r\nimport jwt from 'jsonwebtoken';\r\nimport { jwtRefreshRequired } from './validation';\r\nimport { AuthUserDocument, AuthUserModel, AuthTokenBlocklistModel } from '../../models';\r\n\r\nconst router = express.Router();\r\n\r\nconst NOT_FOUND = 404;\r\nconst FORBIDDEN = 403;\r\nconst BAD_REQUEST = 400;\r\n\r\n/**\r\n * Generates JWT access and refresh tokens for a given user.\r\n * @param auth\r\n * @returns\r\n */\r\nasync function generateCredentials(auth: AuthUserDocument): Promise<JWTCredentials | undefined> {\r\n let jti = undefined;\r\n let blocked = undefined;\r\n do {\r\n jti = crypto.randomUUID();\r\n blocked = await AuthTokenBlocklistModel.findOne({ jti });\r\n } while (blocked != undefined);\r\n const user = await AuthUserModel.findOne({ identifier: auth.identifier }).lean();\r\n if (!user) {\r\n return undefined;\r\n }\r\n let appUser = undefined;\r\n try {\r\n appUser = encodeToBase64(user);\r\n } catch (error) {}\r\n if (!appUser) {\r\n return undefined;\r\n }\r\n let payload: AuthUserPayload = {\r\n identifier: auth.identifier,\r\n jti: jti,\r\n };\r\n\r\n const accessToken = jwt.sign(payload, JwtSecret, { expiresIn: '1h' });\r\n const refreshToken = jwt.sign(payload, JwtRefreshSecret, { expiresIn: '7d' });\r\n return {\r\n accessToken: accessToken,\r\n refreshToken: refreshToken,\r\n appUser: appUser,\r\n };\r\n}\r\n\r\n/**\r\n * Handles user registration by validating input and creating a new user with a hashed password.\r\n * Passes the new user without saving in ``res.locals.authUser`` for the next middleware to use.\r\n * @param req Request & { body: { identifier: string; secret: string } }\r\n * @param res Response & { locals: { authUser: AuthUserDocument } }\r\n * @param next \r\n * @returns \r\n */\r\nexport async function authRegister(\r\n req: Request,\r\n res: Response & { locals: { authUser: AuthUserDocument } },\r\n next: any\r\n): Promise<void> {\r\n let { identifier = undefined, secret = undefined } = req.body || {};\r\n if (!identifier || !secret) {\r\n res.sendStatus(FORBIDDEN);\r\n return;\r\n }\r\n identifier = identifier.toLowerCase();\r\n let user = await AuthUserModel.findOne({ identifier });\r\n if (user) {\r\n res.sendStatus(BAD_REQUEST);\r\n return;\r\n }\r\n res.locals.authUser = new AuthUserModel({\r\n identifier: identifier,\r\n secretHash: await bcrypt.hash(secret, 10),\r\n });\r\n\r\n next();\r\n}\r\n\r\n/**\r\n * Handles user login by validating credentials and generating JWT tokens.\r\n * Passes data in ``res.locals.credentials`` and ``res.locals.authUser`` for the next middleware to use.\r\n * @param req Request & { body: { identifier: string; secret: string } }\r\n * @param res Response & { locals: { credentials: JWTCredentials; authUser: AuthUserDocument } }\r\n * @param next \r\n * @returns \r\n */\r\nexport async function authLogin(\r\n req: Request,\r\n res: Response & { locals: { credentials: JWTCredentials; authUser: AuthUserDocument } },\r\n next: any\r\n): Promise<void> {\r\n let { identifier = undefined, secret = undefined } = req.body || {};\r\n if (!identifier || !secret) {\r\n res.sendStatus(FORBIDDEN);\r\n return;\r\n }\r\n identifier = identifier.toLowerCase();\r\n let user = await AuthUserModel.findOne({ identifier }).select('+secretHash');\r\n if (!user || !user.secretHash) {\r\n res.sendStatus(BAD_REQUEST);\r\n return;\r\n }\r\n if (user.blockedSince) {\r\n res.sendStatus(FORBIDDEN);\r\n return;\r\n }\r\n let isMatch = await bcrypt.compare(secret, user.secretHash);\r\n if (!isMatch) {\r\n res.sendStatus(BAD_REQUEST);\r\n return;\r\n }\r\n let credentials = await generateCredentials(user);\r\n if (!credentials) {\r\n res.sendStatus(BAD_REQUEST);\r\n return;\r\n }\r\n res.locals.credentials = credentials;\r\n res.locals.authUser = user;\r\n next();\r\n}\r\n\r\n/**\r\n * Handles user logout by invalidating the provided refresh token and optionally the access token.\r\n * JWTRefresh Token is required\r\n * @param req \r\n * @param res Response & { locals: { authUserPayload: AuthUserPayload; token: string; authUser: AuthUserDocument } }\r\n * @param next \r\n */\r\nexport async function authLogout(\r\n req: Request,\r\n res: Response & { locals: { authUserPayload: AuthUserPayload; token: string; authUser: AuthUserDocument } },\r\n next: any\r\n): Promise<void> {\r\n await jwtRefreshRequired(req, res, async () => {\r\n let authUserPayload: AuthUserPayload = res.locals.authUserPayload;\r\n let user = await AuthUserModel.findOne({ identifier: authUserPayload.identifier }).select(\r\n '+secretHash'\r\n );\r\n if (!user || !user.secretHash) {\r\n res.sendStatus(BAD_REQUEST);\r\n return;\r\n }\r\n const refreshToken = res.locals.token;\r\n if (!refreshToken) {\r\n res.sendStatus(BAD_REQUEST);\r\n return;\r\n }\r\n const decoded = jwt.decode(refreshToken) as any;\r\n const jti = decoded?.jti;\r\n if (jti) {\r\n const existingBlock = await AuthTokenBlocklistModel.findOne({ jti: jti });\r\n if (!existingBlock) {\r\n await new AuthTokenBlocklistModel({ jti: jti }).save();\r\n }\r\n }\r\n let accessToken = validateString(req.body?.access_token);\r\n if (accessToken) {\r\n const accessTokenDecoded = jwt.decode(accessToken) as any;\r\n let accessTokenJti = accessTokenDecoded?.jti;\r\n if (accessTokenJti) {\r\n const existing = await AuthTokenBlocklistModel.findOne({ jti: accessTokenJti });\r\n if (!existing) {\r\n await new AuthTokenBlocklistModel({ jti: accessTokenJti }).save();\r\n }\r\n }\r\n }\r\n res.locals.authUser = user;\r\n next();\r\n });\r\n}\r\n\r\n/**\r\n * Handles refreshing JWT tokens by validating the provided refresh token and generating new credentials.\r\n * Passes new credentials in ``res.locals.credentials`` and ``res.locals.authUser`` for the next middleware to use.\r\n * @param req \r\n * @param res Response & { locals: { authUserPayload: AuthUserPayload; token: string; credentials: JWTCredentials; authUser: AuthUserDocument } }\r\n * @param next \r\n * @returns \r\n */\r\nexport async function authRefresh(\r\n req: Request,\r\n res: Response & {\r\n locals: {\r\n authUserPayload: AuthUserPayload;\r\n token: string;\r\n credentials: JWTCredentials;\r\n authUser: AuthUserDocument;\r\n };\r\n },\r\n next: any\r\n): Promise<void> {\r\n await jwtRefreshRequired(req, res, async () => {\r\n let authUserPayload: AuthUserPayload = res.locals.authUserPayload;\r\n let user = await AuthUserModel.findOne({ identifier: authUserPayload.identifier }).select(\r\n '+secretHash'\r\n );\r\n if (!user || !user.secretHash) {\r\n res.sendStatus(BAD_REQUEST);\r\n return;\r\n }\r\n const refreshToken = res.locals.token;\r\n if (!refreshToken) {\r\n res.sendStatus(BAD_REQUEST);\r\n return;\r\n }\r\n try {\r\n const decoded = jwt.decode(refreshToken) as any;\r\n const jti = decoded?.jti;\r\n if (jti) {\r\n const existingBlock = await AuthTokenBlocklistModel.findOne({ jti: jti });\r\n if (!existingBlock) {\r\n await new AuthTokenBlocklistModel({ jti: jti }).save();\r\n }\r\n }\r\n let accessToken = validateString(req.body?.access_token);\r\n if (accessToken) {\r\n const accessTokenDecoded = jwt.decode(accessToken) as any;\r\n let accessTokenJti = accessTokenDecoded?.jti;\r\n if (accessTokenJti) {\r\n const existing = await AuthTokenBlocklistModel.findOne({\r\n jti: accessTokenJti,\r\n });\r\n if (!existing) {\r\n await new AuthTokenBlocklistModel({ jti: accessTokenJti }).save();\r\n }\r\n }\r\n }\r\n const payload = jwt.verify(refreshToken, JwtRefreshSecret) as any;\r\n let credentials = await generateCredentials(payload);\r\n if (!credentials) {\r\n res.sendStatus(BAD_REQUEST);\r\n return;\r\n }\r\n res.locals.authUser = user;\r\n res.locals.credentials = credentials;\r\n next();\r\n } catch (err) {\r\n console.log('[WARN] refreshing JWT:', err);\r\n res.sendStatus(BAD_REQUEST);\r\n return;\r\n }\r\n });\r\n}\r\n\r\nexport default router;\r\n", "import { Request, Response } from 'express';\r\nimport jwt from 'jsonwebtoken';\r\nimport { AuthUserPayload } from './types';\r\nimport { JwtRefreshSecret, JwtSecret } from '../../utils';\r\nimport { AuthUserModel, AuthTokenBlocklistModel } from '../../models';\r\n\r\nexport interface TokenVerificationResult {\r\n /**\r\n * Indicates if the token is valid (signature is correct, not blocked, and user is not blocked).\r\n */\r\n isTokenValid: boolean;\r\n /**\r\n * Indicates if the token is expired.\r\n */\r\n isTokenExpired: boolean;\r\n /**\r\n * Indicates if the user associated with the token is blocked.\r\n */\r\n isUserBlocked: boolean;\r\n /**\r\n * The decoded payload from the JWT token, which should contain user information.\r\n */\r\n payload: AuthUserPayload | any;\r\n}\r\n\r\nconst FORBIDDEN = 403;\r\nconst UNAUTHORIZED = 401; // refresh the tokens\r\n\r\n/**\r\n * Express middleware to require a valid JWT token for access. Checks the token against the blocklist and user status.\r\n * Adding user and access token to ``res.locals.authUserPayload`` and ``res.locals.token``\r\n * @param req\r\n * @param res\r\n * @param next\r\n * @returns\r\n */\r\nexport async function jwtRequired(\r\n req: Request,\r\n res: Response & { locals: { authUserPayload: AuthUserPayload; token: string } },\r\n next: any\r\n): Promise<void> {\r\n await validateJwt(req, res, next, JwtSecret);\r\n}\r\n\r\n/**\r\n * Express middleware to require a valid refresh JWT token for access. Checks the token against the blocklist and user status.\r\n * Adding user and access token to ``res.locals.authUserPayload`` and ``res.locals.token``\r\n * @param req\r\n * @param res\r\n * @param next\r\n * @returns\r\n */\r\nexport async function jwtRefreshRequired(\r\n req: Request,\r\n res: Response & { locals: { authUserPayload: AuthUserPayload; token: string } },\r\n next: any\r\n): Promise<void> {\r\n await validateJwt(req, res, next, JwtRefreshSecret);\r\n}\r\n\r\n/**\r\n * Verifies a JWT token and checks for blocklist and user status.\r\n * @param token\r\n * @param jwtSecret\r\n * @returns An object containing validity, expiration status, and payload.\r\n */\r\nexport async function verifyToken(\r\n token: string,\r\n jwtSecret: string\r\n): Promise<TokenVerificationResult> {\r\n try {\r\n const payload = jwt.verify(token, jwtSecret, { ignoreExpiration: true }) as AuthUserPayload;\r\n const jti = payload?.jti;\r\n if (!jti) {\r\n console.log('[WARN] JWT token without jti');\r\n return { isTokenValid: false, isTokenExpired: false, isUserBlocked: false, payload };\r\n }\r\n const existingBlock = await AuthTokenBlocklistModel.findOne({ jti: jti });\r\n if (existingBlock) {\r\n console.log('[WARN] JWT token is blocked');\r\n return { isTokenValid: false, isTokenExpired: false, isUserBlocked: false, payload };\r\n }\r\n const identifier = payload.identifier;\r\n if (identifier) {\r\n const user = await AuthUserModel.findOne({ identifier });\r\n if (!user) {\r\n console.log('[WARN] JWT token for non-existing user');\r\n return { isTokenValid: false, isTokenExpired: false, isUserBlocked: false, payload };\r\n }\r\n if (user.blockedSince != undefined) {\r\n console.log('[WARN] JWT token for blocked user');\r\n return { isTokenValid: false, isTokenExpired: false, isUserBlocked: true, payload };\r\n }\r\n } else {\r\n console.log('[WARN] JWT token without identifier');\r\n return { isTokenValid: false, isTokenExpired: false, isUserBlocked: false, payload };\r\n }\r\n const now = Math.floor(Date.now() / 1000);\r\n if (payload.exp && payload.exp < now) {\r\n if (jwtSecret == JwtSecret) {\r\n console.log('[WARN] Access token expired');\r\n return { isTokenValid: false, isTokenExpired: true, isUserBlocked: false, payload };\r\n } else {\r\n console.log('[WARN] Refresh token expired');\r\n return { isTokenValid: false, isTokenExpired: false, isUserBlocked: false, payload };\r\n }\r\n }\r\n return { isTokenValid: true, isTokenExpired: false, isUserBlocked: false, payload };\r\n } catch (err: any) {\r\n console.log('[WARN] JWT verification error:', err.message);\r\n return {\r\n isTokenValid: false,\r\n isTokenExpired: false,\r\n payload: null,\r\n isUserBlocked: false,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Helper function to validate JWT tokens in Express middleware, used by both jwtRequired and jwtRefreshRequired.\r\n * Checks the token against the blocklist and user status, and passes the decoded payload in ``res.locals.authUserPayload`` if valid.\r\n * ``res.locals.token`` is set to the raw token.\r\n * @param req\r\n * @param res Response & { locals: { authUserPayload: AuthUserPayload; token: string } }\r\n * @param next\r\n * @param jwtSecret\r\n * @returns\r\n */\r\nasync function validateJwt(\r\n req: Request,\r\n res: Response & { locals: { authUserPayload: AuthUserPayload; token: string } },\r\n next: any,\r\n jwtSecret: string\r\n): Promise<\r\n | (Response<any, Record<string, any>> & {\r\n locals: {\r\n authUserPayload: AuthUserPayload;\r\n token: string;\r\n };\r\n })\r\n | undefined\r\n> {\r\n const authHeader = req.headers['authorization'];\r\n if (!authHeader) return res.sendStatus(FORBIDDEN);\r\n const token = authHeader.split(' ')[1];\r\n if (!token) return res.sendStatus(FORBIDDEN);\r\n try {\r\n const result = await verifyToken(token, jwtSecret);\r\n if (result.isTokenExpired) {\r\n console.log('[WARN] Expired JWT token');\r\n return res.sendStatus(UNAUTHORIZED);\r\n }\r\n if (!result.isTokenValid) {\r\n console.log('[WARN] Invalid JWT token');\r\n return res.sendStatus(FORBIDDEN);\r\n }\r\n if (result.isUserBlocked) {\r\n console.log('[WARN] JWT token for blocked user');\r\n return res.sendStatus(FORBIDDEN);\r\n }\r\n res.locals.authUserPayload = result.payload;\r\n res.locals.token = token;\r\n next();\r\n } catch (err) {\r\n console.log('[ERROR] JWT validation error:', err);\r\n return res.sendStatus(FORBIDDEN);\r\n }\r\n}\r\n\r\n/**\r\n * @test TODO not rly tested\r\n * \r\n * @param _socket \r\n * @param _next \r\n * @returns \r\n */\r\nexport async function socketToken(_socket: any, _next: any) {\r\n const token = _socket.handshake.auth?.token;\r\n if (!token) {\r\n // Anonymous user, no token provided\r\n return _next();\r\n }\r\n try {\r\n const verificationResult = await verifyToken(token, JwtSecret);\r\n const isValidChar =\r\n verificationResult.isTokenValid && !verificationResult.isTokenExpired ? '\uD83D\uDFE2' : '\uD83D\uDD34';\r\n console.log(`${isValidChar} Socket verification result: ${JSON.stringify(verificationResult)}`);\r\n if (!verificationResult.isTokenValid) {\r\n if (verificationResult.isTokenExpired) {\r\n return _next(new Error('expired_token'));\r\n }\r\n return _next(new Error('invalid_token'));\r\n }\r\n _socket.user = verificationResult.payload;\r\n _next();\r\n } catch (err) {\r\n return _next(new Error('invalid_token'));\r\n }\r\n}\r\n", "import mongoose from \"mongoose\";\r\n\r\nexport interface AuthUser {\r\n identifier: string;\r\n secretHash: string;\r\n blockedSince: Date;\r\n}\r\n\r\nexport type AuthUserDocument = AuthUser & mongoose.Document;\r\n\r\nconst AuthUserSchema = new mongoose.Schema<AuthUserDocument>(\r\n {\r\n identifier: { type: String, unique: true, required: true },\r\n secretHash: { type: String, select: false },\r\n blockedSince: { type: Date },\r\n },\r\n { collection: 'auth_users', timestamps: true }\r\n);\r\n\r\nexport const AuthUserModel = mongoose.model<AuthUserDocument>('AuthUser', AuthUserSchema);", "import mongoose from \"mongoose\";\r\n\r\nexport interface AuthTokenBlocklist {\r\n jti: string;\r\n}\r\n\r\nexport type AuthTokenBlocklistDocument = AuthTokenBlocklist & mongoose.Document;\r\n\r\nconst AuthTokenBlocklistSchema = new mongoose.Schema<AuthTokenBlocklistDocument>(\r\n {\r\n jti: { type: String, required: true },\r\n },\r\n { collection: 'token_blocklist', timestamps: true }\r\n);\r\n\r\nexport const AuthTokenBlocklistModel = mongoose.model<AuthTokenBlocklistDocument>(\r\n 'AuthTokenBlocklist',\r\n AuthTokenBlocklistSchema\r\n);", "import mongoose from 'mongoose';\r\nimport {\r\n FluentRequestQuery,\r\n fluentRequestQueryAttributes,\r\n FluentMiddleware,\r\n FluentExecParams,\r\n} from './types';\r\nimport { Codec, DefaultResponseBody, PromiseDefaultCodec, QueryBuilder } from '../core/index';\r\n\r\ninterface FluentPatternParameter {\r\n id: string;\r\n ids: string[];\r\n excluded: string[];\r\n filterFields: Record<string, string>;\r\n filter: string;\r\n limit: string;\r\n offset: string;\r\n}\r\n\r\nexport class FluentPatternHandler {\r\n /**\r\n * Singleton instance of FluentPatternHandler. The class is designed\r\n */\r\n private static _singleton: FluentPatternHandler;\r\n /**\r\n * Array of middleware functions to be executed before the main query execution in the exec method. Each function receives the execution parameters and can modify them as needed.\r\n */\r\n private _execMiddlewareFunctions: FluentMiddleware[] = [];\r\n\r\n /**\r\n * Constructor for FluentPatternHandler.\r\n * @param execMiddleware - Optional array of middleware functions to be executed before the main query execution in the exec method.\r\n */\r\n constructor(execMiddleware: FluentMiddleware[] = []) {\r\n if (FluentPatternHandler._singleton) {\r\n throw new Error(\r\n 'FluentPatternHandler is a singleton class. Use FluentPatternHandler.getInstance() to access the instance.'\r\n );\r\n }\r\n this._execMiddlewareFunctions = execMiddleware;\r\n FluentPatternHandler._singleton = this;\r\n }\r\n\r\n /**\r\n * Initializes the singleton instance of FluentPatternHandler with the provided options.\r\n * @param execMiddleware - Optional array of middleware functions to be executed before the main query execution in the exec method.\r\n * @returns Singleton instance of FluentPatternHandler.\r\n */\r\n public static init(execMiddleware: FluentMiddleware[] = []): FluentPatternHandler {\r\n if (FluentPatternHandler._singleton != undefined) {\r\n throw new Error('FluentPatternHandler is already initialized');\r\n }\r\n FluentPatternHandler._singleton = new FluentPatternHandler(execMiddleware);\r\n return FluentPatternHandler._singleton;\r\n }\r\n\r\n /**\r\n * Returns the singleton instance of FluentPatternHandler.\r\n * @returns Singleton instance of FluentPatternHandler.\r\n */\r\n public static getInstance(): FluentPatternHandler {\r\n if (FluentPatternHandler._singleton == undefined) {\r\n throw new Error(\r\n 'FluentPatternHandler instance has not been created yet. Please create an instance before calling getInstance().'\r\n );\r\n }\r\n return FluentPatternHandler._singleton;\r\n }\r\n\r\n /**\r\n * Parses and validates query parameters from the request.\r\n * @param query - The query object from the request.\r\n * @returns Parsed query parameters.\r\n */\r\n private _parseFluentRequestQuery(query: FluentRequestQuery): FluentPatternParameter {\r\n const { filter, limit = '5', offset = '0', id, excluded: excludedJSON, ids: idsJSON } = query;\r\n\r\n const queryKeys = Object.keys(fluentRequestQueryAttributes);\r\n let filterFields: Record<string, string> = {};\r\n for (const [key, value] of Object.entries(query as Record<string, any>)) {\r\n if (queryKeys.includes(key)) continue;\r\n if (value == undefined) continue;\r\n try {\r\n filterFields[key] = typeof value === 'string' ? value : JSON.stringify(value);\r\n } catch (e) {\r\n filterFields[key] = String(value);\r\n }\r\n }\r\n\r\n let excluded: string[] | undefined;\r\n if (excludedJSON) {\r\n try {\r\n excluded = JSON.parse(excludedJSON);\r\n if (!Array.isArray(excluded)) throw new Error('Excluded must be an array');\r\n } catch (error) {\r\n console.warn('[FluentPatternHandler] Invalid excluded parameter:', error);\r\n }\r\n }\r\n\r\n let ids: string[] | undefined;\r\n if (idsJSON) {\r\n try {\r\n ids = JSON.parse(idsJSON);\r\n if (!Array.isArray(ids)) throw new Error('Ids must be an array');\r\n } catch (error) {\r\n console.warn('[FluentPatternHandler] Invalid ids parameter:', error);\r\n }\r\n }\r\n\r\n return { filter, limit, offset, id, excluded, ids, filterFields } as FluentPatternParameter;\r\n }\r\n\r\n /**\r\n * Applies filters to the query builder based on parsed parameters and options.\r\n * @param queryBuilder - The QueryBuilder instance.\r\n * @param params - Parsed query parameters.\r\n * @param config - Query request configuration.\r\n */\r\n private _applyParameters(queryBuilder: QueryBuilder, params: FluentPatternParameter): void {\r\n const { id, ids, filter, excluded } = params;\r\n\r\n if (id) {\r\n queryBuilder.match({ _id: new mongoose.Types.ObjectId(id) });\r\n } else if (ids && ids.length > 0) {\r\n const objectIds = ids.map((id) => new mongoose.Types.ObjectId(id));\r\n queryBuilder.match({ _id: { $in: objectIds } });\r\n } else {\r\n // get allowed filter fields\r\n const modelFilterFields = this._getFilterFieldsForModel(queryBuilder.getConfig().model);\r\n // possible fields filtered by parameter \"?filter=\"\r\n if (filter && modelFilterFields.length > 0) {\r\n const ors = modelFilterFields.map((field) => ({\r\n [field]: { $regex: filter, $options: 'i' },\r\n }));\r\n queryBuilder.match({ $or: ors });\r\n }\r\n // custom filter, but only for allowed fields specified via query parameters (e.g. '?username=')\r\n if (params.filterFields && Object.keys(params.filterFields).length > 0) {\r\n for (const [field, value] of Object.entries(params.filterFields)) {\r\n if (!modelFilterFields.includes(field)) {\r\n continue;\r\n }\r\n const match: Record<string, any> = {};\r\n match[field] = { $regex: value, $options: 'i' };\r\n queryBuilder.match(match);\r\n }\r\n }\r\n if (excluded && excluded.length > 0) {\r\n const objectIds = excluded.map((id) => new mongoose.Types.ObjectId(id));\r\n queryBuilder.match({ _id: { $nin: objectIds } });\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Generates filter fields for the given Mongoose model based on schema options.\r\n * @param model - The Mongoose model.\r\n * @returns Array of filter fields.\r\n */\r\n private _getFilterFieldsForModel(model: mongoose.Model<any>): string[] {\r\n let filterFields: string[] = [];\r\n let schema: mongoose.Schema = model.schema;\r\n schema.eachPath((path: string, type: mongoose.SchemaType) => {\r\n if (type?.options?.filter == true) {\r\n filterFields.push(path);\r\n }\r\n });\r\n return filterFields;\r\n }\r\n\r\n /**\r\n * Builds execution parameters for the query builder.\r\n * @param params - Parsed query parameters.\r\n * @returns Execution parameters.\r\n */\r\n private _buildExecutionConfig(params: FluentPatternParameter): {\r\n isOne: boolean;\r\n limit?: number;\r\n skip?: number;\r\n } {\r\n const { id, limit, offset } = params;\r\n return {\r\n isOne: Boolean(id),\r\n limit: limit === 'full' ? undefined : parseInt(limit || '5', 10),\r\n skip: parseInt(offset || '0', 10),\r\n };\r\n }\r\n\r\n /**\r\n * Executes the query builder with applied filters and returns the result.\r\n * @param params Execution parameters including the query builder and request query.\r\n * @returns\r\n */\r\n public async exec<T = any>(params: FluentExecParams): PromiseDefaultCodec {\r\n try {\r\n if (this._execMiddlewareFunctions && this._execMiddlewareFunctions.length > 0) {\r\n for (const func of this._execMiddlewareFunctions) {\r\n await func(params);\r\n }\r\n }\r\n const queryParams = this._parseFluentRequestQuery(params.req.query as FluentRequestQuery);\r\n this._applyParameters(params.queryBuilder, queryParams);\r\n const execConfig = this._buildExecutionConfig(queryParams);\r\n return await params.queryBuilder.exec(execConfig);\r\n } catch (err) {\r\n console.error('[ERROR - FluentPatternHandler]', err);\r\n return new Codec<DefaultResponseBody>({ data: [], meta: { total: 0 } }, 500);\r\n }\r\n }\r\n}\r\n", "import { Request, Response } from 'express';\r\nimport { DefaultResponseBody, KeysEnum, QueryBuilder } from '../core/index';\r\n\r\nexport interface FluentRequestBody {} // GET requests do not have body\r\n\r\nexport interface FluentRequestQuery {\r\n id?: string;\r\n ids?: string; // as JSON\r\n filter?: string;\r\n offset?: string;\r\n limit?: string;\r\n order?: string;\r\n excluded?: string; // as JSON\r\n}\r\n\r\n/**\r\n * Attributes of FluentRequestQuery used for validation and parsing.\r\n */\r\nexport const fluentRequestQueryAttributes: KeysEnum<FluentRequestQuery> = {\r\n id: '',\r\n ids: '',\r\n filter: '',\r\n offset: '',\r\n limit: '',\r\n order: '',\r\n excluded: '',\r\n};\r\n\r\nexport type FluentExpressRequest = Request<\r\n any,\r\n DefaultResponseBody,\r\n FluentRequestBody,\r\n FluentRequestQuery\r\n>;\r\n\r\nexport type FluentExpressResponse = Response<DefaultResponseBody>;\r\n\r\nexport type FluentExecParams = {\r\n req: FluentExpressRequest;\r\n res: FluentExpressResponse;\r\n queryBuilder: QueryBuilder;\r\n};\r\n\r\nexport type FluentMiddleware = (params: FluentExecParams) => void;\r\n", "import mongoose from 'mongoose';\r\nimport { Codec, DefaultResponseBody, JoinRelation, PromiseDefaultCodec, QueryBuilderConfig } from './types';\r\n\r\nexport class QueryBuilder {\r\n private _config: QueryBuilderConfig;\r\n private _matchConditions: Record<string, any> = {};\r\n private _stages: any[] = [];\r\n private _relations: JoinRelation[] = [];\r\n private _unsetFields: string[] = [];\r\n\r\n constructor(config: QueryBuilderConfig) {\r\n this._config = config;\r\n this._applyPathOptions();\r\n }\r\n\r\n /**\r\n * Generates the aggregation pipeline based on the current configuration of the QueryBuilder.\r\n * @returns\r\n */\r\n public getAggregationPipeline(): any[] {\r\n return this._generatePipeline();\r\n }\r\n\r\n /**\r\n * Returns the current configuration of the QueryBuilder, including model, select fields, and any applied options.\r\n * @returns\r\n */\r\n public getConfig(): QueryBuilderConfig {\r\n return this._config;\r\n }\r\n\r\n /**\r\n * Applies schema-based options such as joins and unset fields.\r\n */\r\n private _applyPathOptions() {\r\n this._generateSchemaJoins(this._config.model.schema);\r\n this._generateSchemaUnsetList(this._config);\r\n }\r\n\r\n /**\r\n * Adds match conditions to the query builder.\r\n * @param match - The match conditions to add.\r\n * @param conjunction - The logical conjunction ('and' or 'or').\r\n * @param append - Whether to append to existing conditions or replace them.\r\n */\r\n match(\r\n match: Record<string, any> | Record<string, any>[],\r\n conjunction: string = 'and',\r\n append: boolean = true\r\n ) {\r\n if (!match || (Array.isArray(match) ? match.length === 0 : Object.keys(match).length === 0))\r\n return;\r\n if (!append) {\r\n this._matchConditions = Array.isArray(match) ? { $and: match } : match;\r\n return;\r\n }\r\n const key = `$${conjunction}`;\r\n if (!this._matchConditions[key]) this._matchConditions[key] = [];\r\n if (Array.isArray(match)) {\r\n this._matchConditions[key].push(...match);\r\n } else {\r\n this._matchConditions[key].push(match);\r\n }\r\n }\r\n\r\n /**\r\n * Adds aggregation stages to the query builder.\r\n * @param stages\r\n * @returns\r\n */\r\n stage(stages: any[] | {} | any) {\r\n if (!stages) return;\r\n if (Array.isArray(stages)) {\r\n this._stages.push(...globalThis.structuredClone(stages));\r\n } else {\r\n this._stages.push(globalThis.structuredClone(stages));\r\n }\r\n }\r\n\r\n /**\r\n * Adds join relations to the query builder.\r\n * @param rels\r\n * @returns\r\n */\r\n join(rels: JoinRelation | JoinRelation[] | null) {\r\n if (!rels) return;\r\n const list = Array.isArray(rels) ? rels : [rels];\r\n list.forEach((rel) => this._relations.push(rel));\r\n }\r\n\r\n /**\r\n * Calculates the $lookup stage for a given JoinRelation.\r\n * @param relation\r\n * @returns\r\n */\r\n private _calculateJoin(relation: JoinRelation) {\r\n if (!(relation instanceof JoinRelation)) throw new Error('relation must be JoinRelation');\r\n return {\r\n $lookup: {\r\n from: relation.ref.collection.name,\r\n localField: relation.localField,\r\n foreignField: '_id',\r\n as: relation.alias,\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Automatically generates JoinRelation objects from schema refs.\r\n * @param model The Mongoose model to scan.\r\n * @param prefix Optional prefix for nested paths (e.g., 'alias.field').\r\n * @returns Array of JoinRelation objects.\r\n */\r\n private _generateSchemaJoins(schema: mongoose.Schema, prefix: string = '') {\r\n schema.eachPath((path: string, schematype: any) => {\r\n const fullPath = prefix ? `${prefix}.${path}` : path;\r\n\r\n if (schematype.options?.ref) {\r\n const refModelName = schematype.options.ref;\r\n try {\r\n const refModel = mongoose.model(refModelName);\r\n let alias = schematype.options?.alias ?? refModel.collection.name;\r\n this.join(new JoinRelation(fullPath, refModel, alias));\r\n } catch (err) {\r\n console.warn(\r\n `[QueryBuilder] Could not resolve ref model '${refModelName}' for path '${fullPath}'`\r\n );\r\n }\r\n }\r\n\r\n if (\r\n schematype instanceof mongoose.Schema.Types.Array &&\r\n (schematype as any).caster?.options?.ref\r\n ) {\r\n const refModelName = (schematype as any).caster.options.ref;\r\n try {\r\n const refModel = mongoose.model(refModelName);\r\n let alias = (schematype as any).caster.options?.alias ?? refModel.collection.name;\r\n this.join(new JoinRelation(fullPath, refModel, alias));\r\n } catch (err) {\r\n console.warn(\r\n `[QueryBuilder] Could not resolve array ref model '${refModelName}' for path '${fullPath}'`\r\n );\r\n }\r\n }\r\n\r\n // if (schematype instanceof mongoose.Schema.Types.Subdocument) { //TODO Testen ob Subdocuments auch so erkannt werden k\u00F6nnen\r\n // joins.push(...this._generateSchemaJoins(model.schema, fullPath));\r\n // }\r\n });\r\n }\r\n\r\n /**\r\n * Generates the list of fields to unset based on schema select options.\r\n * @param config - The query request configuration.\r\n */\r\n private _generateSchemaUnsetList(config: QueryBuilderConfig) {\r\n this._unsetFields = [];\r\n let unset = this._collectSelectFalse(config.model.schema, undefined, config.select);\r\n for (const relation of this._relations) {\r\n unset = unset.concat(\r\n this._collectSelectFalse(relation.ref.schema, relation.alias, config.select)\r\n );\r\n }\r\n this._unsetFields = Array.from(new Set(unset));\r\n }\r\n\r\n /**\r\n * Collects paths from the schema where select is set to false.\r\n * @param schema - The Mongoose schema to scan.\r\n * @param prefix - Optional prefix for nested paths.\r\n * @param select - Optional array of fields to select.\r\n * @returns Array of paths to unset.\r\n */\r\n private _collectSelectFalse(\r\n schema: mongoose.Schema,\r\n prefix: string | undefined = undefined,\r\n select: string[] | undefined = undefined\r\n ): string[] {\r\n const unset: string[] = [];\r\n schema.eachPath((path: string, schematype: any) => {\r\n // If select is specified, only consider fields not in select or with select: false\r\n if (\r\n select &&\r\n select.length > 0 &&\r\n !select.includes(path) &&\r\n schematype?.options?.select !== false\r\n ) {\r\n return;\r\n }\r\n if (schematype?.options?.select === false) {\r\n unset.push(prefix ? `${prefix}.${path}` : path);\r\n }\r\n });\r\n return unset;\r\n }\r\n\r\n /**\r\n * Generates the aggregation pipeline based on joins, stages, match conditions, and unset fields.\r\n * @returns The aggregation pipeline array.\r\n */\r\n private _generatePipeline(): any[] {\r\n const pipeline: any[] = [];\r\n // Add join stages\r\n for (const rel of this._relations) {\r\n pipeline.push(this._calculateJoin(rel));\r\n }\r\n // Add custom stages\r\n pipeline.push(...this._stages);\r\n // Add match conditions\r\n if (Object.keys(this._matchConditions).length) {\r\n pipeline.push({ $match: this._matchConditions });\r\n }\r\n // Add unset fields\r\n if (this._unsetFields.length) {\r\n pipeline.push({ $unset: this._unsetFields });\r\n }\r\n return pipeline;\r\n }\r\n\r\n /**\r\n * Executes the aggregation pipeline and returns the results.\r\n * @param config - Parameters for the query execution.\r\n * @returns The collection response wrapped in a Codec.\r\n */\r\n async exec<T = any>(config?: {\r\n isOne?: boolean;\r\n limit?: number;\r\n skip?: number;\r\n }): PromiseDefaultCodec {\r\n try {\r\n const pipeline = this._generatePipeline();\r\n\r\n const countPipeline = [...pipeline, { $count: 'n' }];\r\n const queryPipeline = [...pipeline];\r\n if (config && !config.isOne) {\r\n if (config.skip) queryPipeline.push({ $skip: config.skip });\r\n if (config.limit) queryPipeline.push({ $limit: config.limit });\r\n }\r\n\r\n const [countRes, res] = await Promise.all([\r\n this._config.model.aggregate(countPipeline).exec(),\r\n this._config.model.aggregate<T>(queryPipeline).exec(),\r\n ]);\r\n\r\n const totalCount = countRes && countRes[0] ? countRes[0].n : 0;\r\n const documents =\r\n config && config.isOne\r\n ? await this._processSingleDocument<T>(res)\r\n : await this._processMultipleDocuments<T>(res);\r\n\r\n return new Codec<DefaultResponseBody>({ data: documents, meta: { total: totalCount } }, 200);\r\n } catch (err) {\r\n console.error('[ERROR - QueryBuilder]', err);\r\n return new Codec<DefaultResponseBody>({ data: [], meta: { total: 0 } }, 500);\r\n }\r\n }\r\n\r\n /**\r\n * Processes a single document from the aggregation result.\r\n * @param res - The aggregation result array.\r\n * @returns The processed document or null if none.\r\n */\r\n private async _processSingleDocument<T>(res: any[]): Promise<T | null> {\r\n if (!res || res.length === 0) {\r\n return null;\r\n }\r\n let doc = this._config.model.hydrate(res[0]);\r\n if (this._config.eachFunc) {\r\n doc = this._config.eachFunc(doc as T);\r\n } else if (this._config.asyncEachFunc) {\r\n doc = await this._config.asyncEachFunc(doc as T);\r\n }\r\n return doc;\r\n }\r\n\r\n /**\r\n * Processes multiple documents from the aggregation result.\r\n * @param res - The aggregation result array.\r\n * @returns The array of processed documents.\r\n */\r\n private async _processMultipleDocuments<T>(res: any[]): Promise<T[]> {\r\n let final = (res || []).map((doc: any) => this._config.model.hydrate(doc));\r\n if (this._config.eachFunc) {\r\n final = final.map(this._config.eachFunc);\r\n } else if (this._config.asyncEachFunc) {\r\n const asyncFinal: T[] = [];\r\n for (const doc of final) {\r\n const newDoc = await this._config.asyncEachFunc(doc);\r\n asyncFinal.push(newDoc);\r\n }\r\n final = asyncFinal;\r\n }\r\n return final;\r\n }\r\n}\r\n", "import mongoose from 'mongoose';\r\n\r\nexport interface DefaultResponseBody extends Record<string, any> {\r\n data?: any[] | any;\r\n meta?: { total?: number };\r\n error?: string;\r\n}\r\n\r\nexport class Codec<T = any> {\r\n content: T;\r\n returnCode: number;\r\n\r\n constructor(content: T, code: number = 202) {\r\n this.content = content;\r\n this.returnCode = code;\r\n }\r\n\r\n sendToClient(res: any) {\r\n if (this.content == null) {\r\n res.status(404).json({});\r\n }\r\n res.status(this.returnCode).json(this.content);\r\n }\r\n\r\n is1xx() {\r\n return this.returnCode >= 100 && this.returnCode <= 199;\r\n }\r\n is2xx() {\r\n return this.returnCode >= 200 && this.returnCode <= 299;\r\n }\r\n is3xx() {\r\n return this.returnCode >= 300 && this.returnCode <= 399;\r\n }\r\n is4xx() {\r\n return this.returnCode >= 400 && this.returnCode <= 499;\r\n }\r\n}\r\n\r\nexport type DefaultCodec = Codec<DefaultResponseBody>;\r\nexport type PromiseDefaultCodec = Promise<Codec<DefaultResponseBody>>;\r\n\r\nexport class JoinRelation<T = any> {\r\n ref: mongoose.Model<T>;\r\n localField: string;\r\n alias: string;\r\n\r\n constructor(localField: string, ref: mongoose.Model<T>, alias: string | undefined = undefined) {\r\n this.ref = ref;\r\n this.localField = localField;\r\n this.alias = alias ? alias : ref.collection.name;\r\n }\r\n}\r\n\r\nexport interface QueryBuilderConfig<T = any> {\r\n model: mongoose.Model<T>;\r\n select?: string[] | undefined; //TODO Eventuell den namen \u00FCberarbeiten\r\n eachFunc?: (doc: any) => any;\r\n asyncEachFunc?: (doc: any) => Promise<any>;\r\n}\r\n\r\nexport enum HttpMethod {\r\n POST = 'post',\r\n GET = 'get',\r\n DELETE = 'delete',\r\n PUT = 'put',\r\n}\r\n\r\nexport interface HTTPRequestConfig {\r\n url: string;\r\n method?: HttpMethod;\r\n /**\r\n * Optional query parameters to be appended to the URL. They will be automatically URL-encoded. For example, { search: 'test', page: '1' } will result in ?search=test&page=1 being appended to the URL.\r\n */\r\n urlSearchParams?: Record<string, string>;\r\n /**\r\n * The body can be an object or a string. If it's an object, it will be automatically stringified as JSON and the Content-Type header will be set to application/json. If it's a string, it will be sent as-is and the Content-Type header will default to application/x-www-form-urlencoded unless explicitly set in the headers.\r\n */\r\n body?: any;\r\n /**\r\n * Optional headers to include in the request. If the body is an object and Content-Type is not explicitly set, it will default to application/json. If the body is a string and Content-Type is not explicitly set, it will default to application/x-www-form-urlencoded. You can override these defaults by providing your own Content-Type header.\r\n */\r\n headers?: Record<string, string>;\r\n}\r\n\r\nexport type KeysEnum<T> = { [P in keyof Required<T>]: any };", "import { HTTPRequestConfig } from './types';\r\n\r\n/**\r\n * Converts an object to a URL-encoded string for form submission.\r\n * With content type application/x-www-form-urlencoded, the body should be a string in the format of key=value&key2=value2.\r\n * @param obj\r\n * @returns\r\n */\r\nexport function formDataParser(obj: Record<string, any>): string {\r\n return new URLSearchParams(obj).toString();\r\n}\r\n\r\n/**\r\n * Executes the HTTP request using axios or fetch as fallback\r\n * @param config RequestConfig\r\n * @returns Promise<T> The response data\r\n */\r\nexport async function httpRequest<T = any>(config: HTTPRequestConfig): Promise<T> {\r\n const url = new URL(config.url);\r\n\r\n if (config.urlSearchParams) {\r\n Object.keys(config.urlSearchParams).forEach((key) => {\r\n url.searchParams.set(key, String((config.urlSearchParams as any)[key]));\r\n });\r\n }\r\n\r\n let body: string | undefined;\r\n let defaultContentType: string = 'application/x-www-form-urlencoded';\r\n\r\n if (config.body) {\r\n if (typeof config.body === 'object') {\r\n body = JSON.stringify(config.body);\r\n defaultContentType = 'application/json';\r\n } else {\r\n body = String(config.body);\r\n }\r\n }\r\n\r\n const fetchImpl = globalThis.fetch;\r\n if (!fetchImpl) {\r\n throw new Error('fetch() is not available. Please use Node.js 18+ or add a fetch polyfill.');\r\n }\r\n\r\n const defaultHeaders: Record<string, string> = {};\r\n if (\r\n !config.headers ||\r\n !Object.keys(config.headers).find((key) => key.toLowerCase() === 'content-type')\r\n ) {\r\n defaultHeaders['Content-Type'] = defaultContentType;\r\n }\r\n\r\n const response = await fetchImpl(url.toString(), {\r\n method: config.method?.toUpperCase() || 'GET',\r\n body,\r\n headers: {\r\n ...defaultHeaders,\r\n ...config.headers,\r\n },\r\n });\r\n const contentType = response.headers.get('content-type') || '';\r\n const isJson = contentType.includes('application/json');\r\n const isBlob = contentType.includes('application/octet-stream');\r\n if (!response.ok) {\r\n const text = await response.text().catch(() => '');\r\n throw new Error(`HTTP ${response.status} ${response.statusText}: ${text}`);\r\n }\r\n let result;\r\n if (isJson) {\r\n result = await response.json().catch(async (error: any) => {\r\n throw new Error(`Failed to parse JSON response: ${error.message}`);\r\n });\r\n } else if (isBlob) {\r\n result = await response.blob().catch(async (error: any) => {\r\n throw new Error(`Failed to get blob response: ${error.message}`);\r\n });\r\n } else {\r\n result = await response.text().catch(async (error: any) => {\r\n throw new Error(`Failed to get text response: ${error.message}`);\r\n });\r\n }\r\n return result as T;\r\n}", "import express from 'express';\r\nimport cors from 'cors';\r\nimport * as core from 'express-serve-static-core';\r\nimport { errorLogger, requestLogger } from './middleware/index';\r\n\r\n/**\r\n * Creates and configures an Express application.\r\n * @example\r\n * ```typescript\r\n * const app = tsledge.createApp();\r\n * app.listen(PORT, () => {\r\n * console.log(`Server running on port ${PORT}`);\r\n * });\r\n * ```\r\n * @returns {core.Express} The configured Express application.\r\n */\r\nexport function createApp(): core.Express {\r\n const app = express();\r\n\r\n app.use(cors());\r\n app.use(express.json());\r\n app.use(express.urlencoded({ extended: true }));\r\n app.use(requestLogger);\r\n app.use(errorLogger);\r\n return app;\r\n}\r\n", "// repl.ts\r\nimport * as tsledge from '../src/index';\r\nimport { start } from 'node:repl';\r\n\r\n// Macht tsledge im globalen Kontext der REPL verf\u00FCgbar\r\n(global as any).tsledge = tsledge;\r\n\r\nconsole.log(\"------------------------------------------\");\r\nconsole.log(\"\uD83D\uDCA1 TSledge scope is available with 'global.tsledge'\");\r\nconsole.log(' (To exit, press Ctrl+C again or Ctrl+D or type .exit)');\r\nconsole.log(\"------------------------------------------\");\r\n\r\n// Startet die REPL mit einem custom Prompt\r\nconst session = start({\r\n prompt: 'tsledge > ',\r\n useGlobal: true // Wichtig, damit das globale 'tsledge' direkt erkannt wird\r\n});"],
5
+ "mappings": "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",
6
+ "names": ["jwt", "mongoose", "mongoose", "FORBIDDEN", "jwt", "mongoose", "mongoose", "HttpMethod", "path", "mongoose", "mongoose", "id", "path", "express", "express"]
7
+ }
@@ -0,0 +1,15 @@
1
+ import { HTTPRequestConfig } from './types';
2
+ /**
3
+ * Converts an object to a URL-encoded string for form submission.
4
+ * With content type application/x-www-form-urlencoded, the body should be a string in the format of key=value&key2=value2.
5
+ * @param obj
6
+ * @returns
7
+ */
8
+ export declare function formDataParser(obj: Record<string, any>): string;
9
+ /**
10
+ * Executes the HTTP request using axios or fetch as fallback
11
+ * @param config RequestConfig
12
+ * @returns Promise<T> The response data
13
+ */
14
+ export declare function httpRequest<T = any>(config: HTTPRequestConfig): Promise<T>;
15
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/core/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE5C;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAE/D;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,CAAC,GAAG,GAAG,EAAE,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,CAAC,CAAC,CAgEhF"}
@@ -0,0 +1,4 @@
1
+ export * from './query-builder';
2
+ export * from './types';
3
+ export * from './http';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC"}
@@ -0,0 +1,96 @@
1
+ import { JoinRelation, PromiseDefaultCodec, QueryBuilderConfig } from './types';
2
+ export declare class QueryBuilder {
3
+ private _config;
4
+ private _matchConditions;
5
+ private _stages;
6
+ private _relations;
7
+ private _unsetFields;
8
+ constructor(config: QueryBuilderConfig);
9
+ /**
10
+ * Generates the aggregation pipeline based on the current configuration of the QueryBuilder.
11
+ * @returns
12
+ */
13
+ getAggregationPipeline(): any[];
14
+ /**
15
+ * Returns the current configuration of the QueryBuilder, including model, select fields, and any applied options.
16
+ * @returns
17
+ */
18
+ getConfig(): QueryBuilderConfig;
19
+ /**
20
+ * Applies schema-based options such as joins and unset fields.
21
+ */
22
+ private _applyPathOptions;
23
+ /**
24
+ * Adds match conditions to the query builder.
25
+ * @param match - The match conditions to add.
26
+ * @param conjunction - The logical conjunction ('and' or 'or').
27
+ * @param append - Whether to append to existing conditions or replace them.
28
+ */
29
+ match(match: Record<string, any> | Record<string, any>[], conjunction?: string, append?: boolean): void;
30
+ /**
31
+ * Adds aggregation stages to the query builder.
32
+ * @param stages
33
+ * @returns
34
+ */
35
+ stage(stages: any[] | {} | any): void;
36
+ /**
37
+ * Adds join relations to the query builder.
38
+ * @param rels
39
+ * @returns
40
+ */
41
+ join(rels: JoinRelation | JoinRelation[] | null): void;
42
+ /**
43
+ * Calculates the $lookup stage for a given JoinRelation.
44
+ * @param relation
45
+ * @returns
46
+ */
47
+ private _calculateJoin;
48
+ /**
49
+ * Automatically generates JoinRelation objects from schema refs.
50
+ * @param model The Mongoose model to scan.
51
+ * @param prefix Optional prefix for nested paths (e.g., 'alias.field').
52
+ * @returns Array of JoinRelation objects.
53
+ */
54
+ private _generateSchemaJoins;
55
+ /**
56
+ * Generates the list of fields to unset based on schema select options.
57
+ * @param config - The query request configuration.
58
+ */
59
+ private _generateSchemaUnsetList;
60
+ /**
61
+ * Collects paths from the schema where select is set to false.
62
+ * @param schema - The Mongoose schema to scan.
63
+ * @param prefix - Optional prefix for nested paths.
64
+ * @param select - Optional array of fields to select.
65
+ * @returns Array of paths to unset.
66
+ */
67
+ private _collectSelectFalse;
68
+ /**
69
+ * Generates the aggregation pipeline based on joins, stages, match conditions, and unset fields.
70
+ * @returns The aggregation pipeline array.
71
+ */
72
+ private _generatePipeline;
73
+ /**
74
+ * Executes the aggregation pipeline and returns the results.
75
+ * @param config - Parameters for the query execution.
76
+ * @returns The collection response wrapped in a Codec.
77
+ */
78
+ exec<T = any>(config?: {
79
+ isOne?: boolean;
80
+ limit?: number;
81
+ skip?: number;
82
+ }): PromiseDefaultCodec;
83
+ /**
84
+ * Processes a single document from the aggregation result.
85
+ * @param res - The aggregation result array.
86
+ * @returns The processed document or null if none.
87
+ */
88
+ private _processSingleDocument;
89
+ /**
90
+ * Processes multiple documents from the aggregation result.
91
+ * @param res - The aggregation result array.
92
+ * @returns The array of processed documents.
93
+ */
94
+ private _processMultipleDocuments;
95
+ }
96
+ //# sourceMappingURL=query-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-builder.d.ts","sourceRoot":"","sources":["../../src/core/query-builder.ts"],"names":[],"mappings":"AACA,OAAO,EAA8B,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE5G,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,UAAU,CAAsB;IACxC,OAAO,CAAC,YAAY,CAAgB;gBAExB,MAAM,EAAE,kBAAkB;IAKtC;;;OAGG;IACI,sBAAsB,IAAI,GAAG,EAAE;IAItC;;;OAGG;IACI,SAAS,IAAI,kBAAkB;IAItC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAKzB;;;;;OAKG;IACH,KAAK,CACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAClD,WAAW,GAAE,MAAc,EAC3B,MAAM,GAAE,OAAc;IAiBxB;;;;OAIG;IACH,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG;IAS9B;;;;OAIG;IACH,IAAI,CAAC,IAAI,EAAE,YAAY,GAAG,YAAY,EAAE,GAAG,IAAI;IAM/C;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAYtB;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;IAuC5B;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAWhC;;;;;;OAMG;IACH,OAAO,CAAC,mBAAmB;IAuB3B;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAmBzB;;;;OAIG;IACG,IAAI,CAAC,CAAC,GAAG,GAAG,EAAE,MAAM,CAAC,EAAE;QAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GAAG,mBAAmB;IA6BvB;;;;OAIG;YACW,sBAAsB;IAapC;;;;OAIG;YACW,yBAAyB;CAcxC"}
@@ -0,0 +1,58 @@
1
+ import mongoose from 'mongoose';
2
+ export interface DefaultResponseBody extends Record<string, any> {
3
+ data?: any[] | any;
4
+ meta?: {
5
+ total?: number;
6
+ };
7
+ error?: string;
8
+ }
9
+ export declare class Codec<T = any> {
10
+ content: T;
11
+ returnCode: number;
12
+ constructor(content: T, code?: number);
13
+ sendToClient(res: any): void;
14
+ is1xx(): boolean;
15
+ is2xx(): boolean;
16
+ is3xx(): boolean;
17
+ is4xx(): boolean;
18
+ }
19
+ export type DefaultCodec = Codec<DefaultResponseBody>;
20
+ export type PromiseDefaultCodec = Promise<Codec<DefaultResponseBody>>;
21
+ export declare class JoinRelation<T = any> {
22
+ ref: mongoose.Model<T>;
23
+ localField: string;
24
+ alias: string;
25
+ constructor(localField: string, ref: mongoose.Model<T>, alias?: string | undefined);
26
+ }
27
+ export interface QueryBuilderConfig<T = any> {
28
+ model: mongoose.Model<T>;
29
+ select?: string[] | undefined;
30
+ eachFunc?: (doc: any) => any;
31
+ asyncEachFunc?: (doc: any) => Promise<any>;
32
+ }
33
+ export declare enum HttpMethod {
34
+ POST = "post",
35
+ GET = "get",
36
+ DELETE = "delete",
37
+ PUT = "put"
38
+ }
39
+ export interface HTTPRequestConfig {
40
+ url: string;
41
+ method?: HttpMethod;
42
+ /**
43
+ * Optional query parameters to be appended to the URL. They will be automatically URL-encoded. For example, { search: 'test', page: '1' } will result in ?search=test&page=1 being appended to the URL.
44
+ */
45
+ urlSearchParams?: Record<string, string>;
46
+ /**
47
+ * The body can be an object or a string. If it's an object, it will be automatically stringified as JSON and the Content-Type header will be set to application/json. If it's a string, it will be sent as-is and the Content-Type header will default to application/x-www-form-urlencoded unless explicitly set in the headers.
48
+ */
49
+ body?: any;
50
+ /**
51
+ * Optional headers to include in the request. If the body is an object and Content-Type is not explicitly set, it will default to application/json. If the body is a string and Content-Type is not explicitly set, it will default to application/x-www-form-urlencoded. You can override these defaults by providing your own Content-Type header.
52
+ */
53
+ headers?: Record<string, string>;
54
+ }
55
+ export type KeysEnum<T> = {
56
+ [P in keyof Required<T>]: any;
57
+ };
58
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAEhC,MAAM,WAAW,mBAAoB,SAAQ,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAC9D,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;IACnB,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,KAAK,CAAC,CAAC,GAAG,GAAG;IACxB,OAAO,EAAE,CAAC,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;gBAEP,OAAO,EAAE,CAAC,EAAE,IAAI,GAAE,MAAY;IAK1C,YAAY,CAAC,GAAG,EAAE,GAAG;IAOrB,KAAK;IAGL,KAAK;IAGL,KAAK;IAGL,KAAK;CAGN;AAED,MAAM,MAAM,YAAY,GAAG,KAAK,CAAC,mBAAmB,CAAC,CAAC;AACtD,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC;AAEtE,qBAAa,YAAY,CAAC,CAAC,GAAG,GAAG;IAC/B,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;gBAEF,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,GAAE,MAAM,GAAG,SAAqB;CAK9F;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,GAAG;IACzC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,CAAC;IAC7B,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;CAC5C;AAED,oBAAY,UAAU;IACpB,IAAI,SAAS;IACb,GAAG,QAAQ;IACX,MAAM,WAAW;IACjB,GAAG,QAAQ;CACZ;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC;;OAEG;IACH,IAAI,CAAC,EAAE,GAAG,CAAC;IACX;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG;CAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './mongodb';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Connects to MongoDB using Mongoose
3
+ * @param uri
4
+ */
5
+ export declare function connectMongoDB(uri: string): Promise<void>;
6
+ //# sourceMappingURL=mongodb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mongodb.d.ts","sourceRoot":"","sources":["../../src/db/mongodb.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,iBAY/C"}
@@ -0,0 +1,4 @@
1
+ export declare const EXIT_CODE_SUCCESS = 0;
2
+ export declare const EXIT_CODE_GENERAL_ERROR = 1;
3
+ export declare const EXIT_CODE_INVALID_CONFIG = 2;
4
+ //# sourceMappingURL=exitCodes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exitCodes.d.ts","sourceRoot":"","sources":["../src/exitCodes.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,IAAI,CAAC;AACnC,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,wBAAwB,IAAI,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { FluentMiddleware, FluentExecParams } from './types';
2
+ import { PromiseDefaultCodec } from '../core/index';
3
+ export declare class FluentPatternHandler {
4
+ /**
5
+ * Singleton instance of FluentPatternHandler. The class is designed
6
+ */
7
+ private static _singleton;
8
+ /**
9
+ * Array of middleware functions to be executed before the main query execution in the exec method. Each function receives the execution parameters and can modify them as needed.
10
+ */
11
+ private _execMiddlewareFunctions;
12
+ /**
13
+ * Constructor for FluentPatternHandler.
14
+ * @param execMiddleware - Optional array of middleware functions to be executed before the main query execution in the exec method.
15
+ */
16
+ constructor(execMiddleware?: FluentMiddleware[]);
17
+ /**
18
+ * Initializes the singleton instance of FluentPatternHandler with the provided options.
19
+ * @param execMiddleware - Optional array of middleware functions to be executed before the main query execution in the exec method.
20
+ * @returns Singleton instance of FluentPatternHandler.
21
+ */
22
+ static init(execMiddleware?: FluentMiddleware[]): FluentPatternHandler;
23
+ /**
24
+ * Returns the singleton instance of FluentPatternHandler.
25
+ * @returns Singleton instance of FluentPatternHandler.
26
+ */
27
+ static getInstance(): FluentPatternHandler;
28
+ /**
29
+ * Parses and validates query parameters from the request.
30
+ * @param query - The query object from the request.
31
+ * @returns Parsed query parameters.
32
+ */
33
+ private _parseFluentRequestQuery;
34
+ /**
35
+ * Applies filters to the query builder based on parsed parameters and options.
36
+ * @param queryBuilder - The QueryBuilder instance.
37
+ * @param params - Parsed query parameters.
38
+ * @param config - Query request configuration.
39
+ */
40
+ private _applyParameters;
41
+ /**
42
+ * Generates filter fields for the given Mongoose model based on schema options.
43
+ * @param model - The Mongoose model.
44
+ * @returns Array of filter fields.
45
+ */
46
+ private _getFilterFieldsForModel;
47
+ /**
48
+ * Builds execution parameters for the query builder.
49
+ * @param params - Parsed query parameters.
50
+ * @returns Execution parameters.
51
+ */
52
+ private _buildExecutionConfig;
53
+ /**
54
+ * Executes the query builder with applied filters and returns the result.
55
+ * @param params Execution parameters including the query builder and request query.
56
+ * @returns
57
+ */
58
+ exec<T = any>(params: FluentExecParams): PromiseDefaultCodec;
59
+ }
60
+ //# sourceMappingURL=fluent-pattern-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fluent-pattern-handler.d.ts","sourceRoot":"","sources":["../../src/fluent-interface/fluent-pattern-handler.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EAA8B,mBAAmB,EAAgB,MAAM,eAAe,CAAC;AAY9F,qBAAa,oBAAoB;IAC/B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,UAAU,CAAuB;IAChD;;OAEG;IACH,OAAO,CAAC,wBAAwB,CAA0B;IAE1D;;;OAGG;gBACS,cAAc,GAAE,gBAAgB,EAAO;IAUnD;;;;OAIG;WACW,IAAI,CAAC,cAAc,GAAE,gBAAgB,EAAO,GAAG,oBAAoB;IAQjF;;;OAGG;WACW,WAAW,IAAI,oBAAoB;IASjD;;;;OAIG;IACH,OAAO,CAAC,wBAAwB;IAsChC;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAoCxB;;;;OAIG;IACH,OAAO,CAAC,wBAAwB;IAWhC;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IAa7B;;;;OAIG;IACU,IAAI,CAAC,CAAC,GAAG,GAAG,EAAE,MAAM,EAAE,gBAAgB,GAAG,mBAAmB;CAgB1E"}
@@ -0,0 +1,3 @@
1
+ export * from './fluent-pattern-handler';
2
+ export * from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fluent-interface/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,SAAS,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { Request, Response } from 'express';
2
+ import { DefaultResponseBody, KeysEnum, QueryBuilder } from '../core/index';
3
+ export interface FluentRequestBody {
4
+ }
5
+ export interface FluentRequestQuery {
6
+ id?: string;
7
+ ids?: string;
8
+ filter?: string;
9
+ offset?: string;
10
+ limit?: string;
11
+ order?: string;
12
+ excluded?: string;
13
+ }
14
+ /**
15
+ * Attributes of FluentRequestQuery used for validation and parsing.
16
+ */
17
+ export declare const fluentRequestQueryAttributes: KeysEnum<FluentRequestQuery>;
18
+ export type FluentExpressRequest = Request<any, DefaultResponseBody, FluentRequestBody, FluentRequestQuery>;
19
+ export type FluentExpressResponse = Response<DefaultResponseBody>;
20
+ export type FluentExecParams = {
21
+ req: FluentExpressRequest;
22
+ res: FluentExpressResponse;
23
+ queryBuilder: QueryBuilder;
24
+ };
25
+ export type FluentMiddleware = (params: FluentExecParams) => void;
26
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/fluent-interface/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE5E,MAAM,WAAW,iBAAiB;CAAG;AAErC,MAAM,WAAW,kBAAkB;IACjC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CAAC,kBAAkB,CAQrE,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,OAAO,CACxC,GAAG,EACH,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,CACnB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC,mBAAmB,CAAC,CAAC;AAElE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,oBAAoB,CAAC;IAC1B,GAAG,EAAE,qBAAqB,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC"}
@@ -0,0 +1,10 @@
1
+ export * from './db/index';
2
+ export * from './middleware/index';
3
+ export * from './fluent-interface/index';
4
+ export * from './core/index';
5
+ export * from './utils/index';
6
+ export * from './models/index';
7
+ export * from './app';
8
+ export * from './types';
9
+ export * from './exitCodes';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './session';
2
+ export * from './validation';
3
+ export * from './types';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/middleware/authentication/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC"}
@@ -0,0 +1,63 @@
1
+ import { Request, Response } from 'express';
2
+ import { JWTCredentials, AuthUserPayload } from './types';
3
+ import { AuthUserDocument } from '../../models';
4
+ declare const router: import("express-serve-static-core").Router;
5
+ /**
6
+ * Handles user registration by validating input and creating a new user with a hashed password.
7
+ * Passes the new user without saving in ``res.locals.authUser`` for the next middleware to use.
8
+ * @param req Request & { body: { identifier: string; secret: string } }
9
+ * @param res Response & { locals: { authUser: AuthUserDocument } }
10
+ * @param next
11
+ * @returns
12
+ */
13
+ export declare function authRegister(req: Request, res: Response & {
14
+ locals: {
15
+ authUser: AuthUserDocument;
16
+ };
17
+ }, next: any): Promise<void>;
18
+ /**
19
+ * Handles user login by validating credentials and generating JWT tokens.
20
+ * Passes data in ``res.locals.credentials`` and ``res.locals.authUser`` for the next middleware to use.
21
+ * @param req Request & { body: { identifier: string; secret: string } }
22
+ * @param res Response & { locals: { credentials: JWTCredentials; authUser: AuthUserDocument } }
23
+ * @param next
24
+ * @returns
25
+ */
26
+ export declare function authLogin(req: Request, res: Response & {
27
+ locals: {
28
+ credentials: JWTCredentials;
29
+ authUser: AuthUserDocument;
30
+ };
31
+ }, next: any): Promise<void>;
32
+ /**
33
+ * Handles user logout by invalidating the provided refresh token and optionally the access token.
34
+ * JWTRefresh Token is required
35
+ * @param req
36
+ * @param res Response & { locals: { authUserPayload: AuthUserPayload; token: string; authUser: AuthUserDocument } }
37
+ * @param next
38
+ */
39
+ export declare function authLogout(req: Request, res: Response & {
40
+ locals: {
41
+ authUserPayload: AuthUserPayload;
42
+ token: string;
43
+ authUser: AuthUserDocument;
44
+ };
45
+ }, next: any): Promise<void>;
46
+ /**
47
+ * Handles refreshing JWT tokens by validating the provided refresh token and generating new credentials.
48
+ * Passes new credentials in ``res.locals.credentials`` and ``res.locals.authUser`` for the next middleware to use.
49
+ * @param req
50
+ * @param res Response & { locals: { authUserPayload: AuthUserPayload; token: string; credentials: JWTCredentials; authUser: AuthUserDocument } }
51
+ * @param next
52
+ * @returns
53
+ */
54
+ export declare function authRefresh(req: Request, res: Response & {
55
+ locals: {
56
+ authUserPayload: AuthUserPayload;
57
+ token: string;
58
+ credentials: JWTCredentials;
59
+ authUser: AuthUserDocument;
60
+ };
61
+ }, next: any): Promise<void>;
62
+ export default router;
63
+ //# sourceMappingURL=session.d.ts.map