fiberx-backend-toolkit 0.1.21 → 1.0.1

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 (67) hide show
  1. package/README.md +207 -139
  2. package/dist/code_templates/sequelize_code_template.d.ts +1 -1
  3. package/dist/code_templates/sequelize_code_template.js +127 -74
  4. package/dist/config/constants.d.ts +1 -0
  5. package/dist/config/constants.js +82 -15
  6. package/dist/database/connectors/sequelize_connector.d.ts +2 -0
  7. package/dist/database/connectors/sequelize_connector.js +43 -21
  8. package/dist/database/main.d.ts +3 -2
  9. package/dist/database/main.js +4 -2
  10. package/dist/database/schema/schema_diff_util.d.ts +0 -1
  11. package/dist/database/schema/schema_diff_util.js +7 -15
  12. package/dist/database/scripts/create_schema_script.js +6 -3
  13. package/dist/database/scripts/make_migrations_script.js +17 -10
  14. package/dist/database/scripts/migration_runner_script.d.ts +3 -1
  15. package/dist/database/scripts/migration_runner_script.js +58 -23
  16. package/dist/database/scripts/seeder_runner_script.d.ts +3 -1
  17. package/dist/database/scripts/seeder_runner_script.js +49 -17
  18. package/dist/database/scripts/sequelize_model_generator_script.d.ts +2 -2
  19. package/dist/database/scripts/sequelize_model_generator_script.js +11 -5
  20. package/dist/index.d.ts +7 -0
  21. package/dist/index.js +7 -0
  22. package/dist/mailer/main.d.ts +1 -1
  23. package/dist/mailer/processors/email_delivery_processor.js +45 -13
  24. package/dist/mailer/processors/email_enqueue_processor.js +23 -7
  25. package/dist/mailer/utils/mailer_data_loader_util.d.ts +4 -4
  26. package/dist/mailer/utils/mailer_data_loader_util.js +5 -5
  27. package/dist/middle_ware/authentication_middle_ware.d.ts +3 -3
  28. package/dist/middle_ware/authentication_middle_ware.js +27 -25
  29. package/dist/middle_ware/cookie_manager_middle_ware.js +1 -1
  30. package/dist/middle_ware/main.d.ts +3 -2
  31. package/dist/middle_ware/main.js +4 -2
  32. package/dist/middle_ware/rate_limiter_middle_ware.js +0 -1
  33. package/dist/middle_ware/request_logger_middle_ware.js +2 -1
  34. package/dist/middle_ware/response_formatter_middle_ware.js +5 -4
  35. package/dist/middle_ware/secure_headers_middle_ware.js +2 -1
  36. package/dist/rbac/rbac_loader_util.js +2 -2
  37. package/dist/storage/drivers/gcs_storage_driver.js +5 -5
  38. package/dist/storage/drivers/local_storage_driver.js +2 -2
  39. package/dist/storage/main.d.ts +1 -1
  40. package/dist/storage/processors/file_upload_processor.js +4 -4
  41. package/dist/storage/utils/storage_driver_util.d.ts +1 -1
  42. package/dist/storage/utils/storage_driver_util.js +12 -10
  43. package/dist/types/express_decelaration.d.ts +1 -1
  44. package/dist/types/express_decelaration.js +0 -1
  45. package/dist/types/middle_ware_type.d.ts +14 -12
  46. package/dist/types/middle_ware_type.js +0 -2
  47. package/dist/types/schema_type.js +0 -1
  48. package/dist/types/util_type.js +0 -1
  49. package/dist/utils/content_manager_util.js +11 -9
  50. package/dist/utils/crypto_key_util.js +9 -10
  51. package/dist/utils/encryptor_decryptor_util.js +19 -9
  52. package/dist/utils/env_manager_util.d.ts +1 -0
  53. package/dist/utils/env_manager_util.js +10 -2
  54. package/dist/utils/fs_actions_util.js +1 -1
  55. package/dist/utils/input_transformer_util.js +11 -25
  56. package/dist/utils/input_validator_util.d.ts +1 -1
  57. package/dist/utils/input_validator_util.js +75 -27
  58. package/dist/utils/logger_util.d.ts +2 -2
  59. package/dist/utils/logger_util.js +23 -9
  60. package/dist/utils/main.d.ts +1 -1
  61. package/dist/utils/safe_execute_util.js +21 -11
  62. package/dist/utils/sql_formatter_util.js +1 -5
  63. package/dist/utils/totp_service_util.js +3 -7
  64. package/dist/utils/uuid_gen_util.js +6 -2
  65. package/dist/validators/file_validator_util.js +2 -2
  66. package/dist/validators/query_validator_util.js +3 -3
  67. package/package.json +68 -2
@@ -10,7 +10,9 @@ const local_storage_driver_1 = __importDefault(require("../../storage/drivers/lo
10
10
  class StorageDriverUtil {
11
11
  static instance = null;
12
12
  static logger = new main_1.LoggerUtil("storage_driver_util");
13
- static env_manager = main_1.EnvManagerUtil.getInstance();
13
+ static get env_manager() {
14
+ return main_1.EnvManagerUtil.getInstance();
15
+ }
14
16
  /**
15
17
  * Get initialized storage driver (singleton)
16
18
  */
@@ -42,9 +44,12 @@ class StorageDriverUtil {
42
44
  if (main_1.InputValidatorUtil.isLive()) {
43
45
  const driver_type = StorageDriverUtil.env_manager.getEnvVar(constants_1.FILE_UPLOAD_ENV_KEYS.STORAGE_DRIVER_NAME, "");
44
46
  switch (driver_type?.toLowerCase()) {
45
- case "local": return StorageDriverUtil.initLocalDriver();
46
- case "gcs": return await StorageDriverUtil.initGCSDriver();
47
- default: throw new Error(`Unsupported storage driver type '${driver_type}' in live environment`);
47
+ case "local":
48
+ return StorageDriverUtil.initLocalDriver();
49
+ case "gcs":
50
+ return await StorageDriverUtil.initGCSDriver();
51
+ default:
52
+ throw new Error(`Unsupported storage driver type '${driver_type}' in live environment`);
48
53
  }
49
54
  }
50
55
  throw new Error("Unsupported environment for storage driver");
@@ -66,7 +71,7 @@ class StorageDriverUtil {
66
71
  const config = {
67
72
  type: "local",
68
73
  base_dir,
69
- public_base_url
74
+ public_base_url,
70
75
  };
71
76
  const driver = new local_storage_driver_1.default();
72
77
  await driver.initialize(config);
@@ -79,23 +84,20 @@ class StorageDriverUtil {
79
84
  static async initGCSDriver() {
80
85
  const project_id = StorageDriverUtil.env_manager.getEnvVar(constants_1.FILE_UPLOAD_ENV_KEYS.GCS_PROJECT_ID, "");
81
86
  const bucket_name = StorageDriverUtil.env_manager.getEnvVar(constants_1.FILE_UPLOAD_ENV_KEYS.GCS_BUCKET_NAME, "");
82
- ;
83
87
  const client_email = StorageDriverUtil.env_manager.getEnvVar(constants_1.FILE_UPLOAD_ENV_KEYS.GCS_CLIENT_EMAIL, "");
84
- ;
85
88
  const private_key = StorageDriverUtil.env_manager.getEnvVar(constants_1.FILE_UPLOAD_ENV_KEYS.GCS_PRIVATE_KEY, "");
86
- ;
87
89
  if (!project_id || !bucket_name || !client_email || !private_key) {
88
90
  throw new Error("Missing required GCS environment variables");
89
91
  }
90
92
  const credentials = {
91
93
  client_email,
92
- private_key: private_key.replace(/\\n/g, "\n")
94
+ private_key: private_key.replace(/\\n/g, "\n"),
93
95
  };
94
96
  const config = {
95
97
  type: "gcs",
96
98
  project_id,
97
99
  bucket_name,
98
- credentials
100
+ credentials,
99
101
  };
100
102
  const driver = new gcs_storage_driver_1.default();
101
103
  await driver.initialize(config);
@@ -1,4 +1,3 @@
1
- import "express-serve-static-core";
2
1
  declare module "express-serve-static-core" {
3
2
  interface Response {
4
3
  errResponse: (code?: number, msg?: string, data?: any) => Response;
@@ -17,3 +16,4 @@ declare module "express-serve-static-core" {
17
16
  clientIp?: string;
18
17
  }
19
18
  }
19
+ export {};
@@ -1,3 +1,2 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- require("express-serve-static-core");
@@ -65,6 +65,7 @@ export interface DefaultRequestInfo {
65
65
  device_id?: string;
66
66
  origin_url: string;
67
67
  request_id: string;
68
+ permission_name?: string;
68
69
  }
69
70
  export interface DefaultAccessTokenPayload {
70
71
  type: string;
@@ -79,16 +80,17 @@ export interface DefaultRefreshTokenPayload {
79
80
  device_id: string;
80
81
  }
81
82
  export interface AuthenticatorOptions<TRequestInfo extends DefaultRequestInfo = DefaultRequestInfo, TAccessPayload extends DefaultAccessTokenPayload = DefaultAccessTokenPayload, TRefreshPayload extends DefaultRefreshTokenPayload = DefaultRefreshTokenPayload, TSessionModel extends Model = Model, TLoginChallengeModel extends Model = Model, TActorModel extends Model = Model> {
82
- extractRequestInfoMethod: (req: Request) => Promise<TRequestInfo | null>;
83
- validateAccessTokenMethod: (access_token: string, requestInfo?: TRequestInfo) => Promise<TAccessPayload | null>;
84
- validateRefreshTokenMethod: (refresh_token: string, requestInfo?: TRequestInfo) => Promise<TRefreshPayload | null>;
85
- loadActorMethod(actor_type: string, actor_id: number | string, requestInfo?: TRequestInfo): Promise<TActorModel | null>;
86
- loadMemberSessionMethod(member_id: number | string, session_id: number | string, request_info?: TRequestInfo, is_2fa_validated?: boolean): Promise<TSessionModel | null>;
87
- loadMemberLoginChallenegeMethod(member_id: number | string, challenge_id: number | string, request_info?: TRequestInfo, is_2fa_validated?: boolean): Promise<TLoginChallengeModel | null>;
88
- getActorPermissionsMethod(actor_id: number | string, role_ids: (number | string)[]): Promise<string[]>;
89
- validateActorHasPermissionMethod(request_info: TRequestInfo): Promise<boolean>;
90
- requireNoAuthMiddleWareMethod(req: Request, res: Response, next: NextFunction): Promise<void | Response>;
91
- requirePartialAuthMiddleWareMethod(req: Request, res: Response, next: NextFunction): Promise<void | Response>;
92
- requireFullAuthMiddleWareMethod(req: Request, res: Response, next: NextFunction): Promise<void | Response>;
93
- requireAppAuthMiddleWareMethod(req: Request, res: Response, next: NextFunction): Promise<void | Response>;
83
+ extractRequestInfoMethod?: (req: Request) => Promise<TRequestInfo | null>;
84
+ validateAccessTokenMethod?: (access_token: string, requestInfo?: TRequestInfo) => Promise<TAccessPayload | null>;
85
+ validateRefreshTokenMethod?: (refresh_token: string, requestInfo?: TRequestInfo) => Promise<TRefreshPayload | null>;
86
+ loadActorMethod?(actor_type: string, actor_id: number | string, requestInfo?: TRequestInfo): Promise<TActorModel | null>;
87
+ loadMemberSessionMethod?(member_id: number | string, session_id: number | string, request_info?: TRequestInfo, is_2fa_validated?: boolean): Promise<TSessionModel | null>;
88
+ loadMemberLoginChallengeMethod?(member_id: number | string, challenge_id: number | string, request_info?: TRequestInfo, is_2fa_validated?: boolean): Promise<TLoginChallengeModel | null>;
89
+ loadMemberLoginChallenegeMethod?(member_id: number | string, challenge_id: number | string, request_info?: TRequestInfo, is_2fa_validated?: boolean): Promise<TLoginChallengeModel | null>;
90
+ getActorPermissionsMethod?(actor_id: number | string, role_ids: (number | string)[]): Promise<string[]>;
91
+ validateActorHasPermissionMethod?(request_info: TRequestInfo, req?: Request): Promise<boolean>;
92
+ requireNoAuthMiddleWareMethod?(req: Request, res: Response, next: NextFunction): Promise<void | Response>;
93
+ requirePartialAuthMiddleWareMethod?(req: Request, res: Response, next: NextFunction): Promise<void | Response>;
94
+ requireFullAuthMiddleWareMethod?(req: Request, res: Response, next: NextFunction): Promise<void | Response>;
95
+ requireAppAuthMiddleWareMethod?(req: Request, res: Response, next: NextFunction): Promise<void | Response>;
94
96
  }
@@ -1,4 +1,2 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- ;
4
- ;
@@ -1,3 +1,2 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- ;
@@ -8,4 +8,3 @@ var ErrorHandlingStrategyEnum;
8
8
  ErrorHandlingStrategyEnum[ErrorHandlingStrategyEnum["THROW_ERROR"] = 2] = "THROW_ERROR";
9
9
  ErrorHandlingStrategyEnum[ErrorHandlingStrategyEnum["CONTROLLER_ERROR"] = 3] = "CONTROLLER_ERROR";
10
10
  })(ErrorHandlingStrategyEnum || (exports.ErrorHandlingStrategyEnum = ErrorHandlingStrategyEnum = {}));
11
- ;
@@ -16,30 +16,32 @@ class ContentManagerUtil {
16
16
  content_url_template;
17
17
  default_language;
18
18
  constructor() {
19
- this.content_cache_ttl_ms = this.env_manager.getEnvVar(constants_1.CONTENT_CACHE_TTL_KEY, constants_1.DEFAULT_CONTENT_CACHE_TTL) ?? constants_1.DEFAULT_CONTENT_CACHE_TTL;
19
+ this.content_cache_ttl_ms =
20
+ this.env_manager.getEnvVar(constants_1.CONTENT_CACHE_TTL_KEY, constants_1.DEFAULT_CONTENT_CACHE_TTL) ??
21
+ constants_1.DEFAULT_CONTENT_CACHE_TTL;
20
22
  this.cache = new main_1.InMemoryCacheUtil();
21
23
  this.content_url_template = this.env_manager.getEnvVar(constants_1.CONTENT_URL_KEY, constants_1.DEFAULT_CONTENT_URL);
22
- this.default_language = this.env_manager.getEnvVar(constants_1.CONTENT_LANG_KEY, constants_1.DEFAULT_CONTENT_LANG) ?? constants_1.DEFAULT_CONTENT_LANG;
24
+ this.default_language =
25
+ this.env_manager.getEnvVar(constants_1.CONTENT_LANG_KEY, constants_1.DEFAULT_CONTENT_LANG) ??
26
+ constants_1.DEFAULT_CONTENT_LANG;
23
27
  this.cleanUpCache();
24
28
  }
25
29
  // Method to clean cache up
26
30
  cleanUpCache() {
27
31
  //periodic cleanup (every 2 minutes)
28
- setInterval(() => { this.cache.cleanup(); }, 120_000);
32
+ setInterval(() => {
33
+ this.cache.cleanup();
34
+ }, 120_000);
29
35
  }
30
36
  getCacheKey(type, lang) {
31
37
  return `content:${type}:${lang}`;
32
38
  }
33
39
  resolvePath(obj, path) {
34
- return path
35
- .split(".")
36
- .reduce((acc, key) => (acc ? acc[key] : undefined), obj);
40
+ return path.split(".").reduce((acc, key) => (acc ? acc[key] : undefined), obj);
37
41
  }
38
42
  // Method to Load content from remote JSON endpoint
39
43
  async loadContent(type, lang) {
40
- const url = this.content_url_template
41
- ?.replace("{{type}}", type)
42
- ?.replace("{{lang}}", lang);
44
+ const url = this.content_url_template?.replace("{{type}}", type)?.replace("{{lang}}", lang);
43
45
  if (!url) {
44
46
  throw new Error(`Invalid content URL for type=${type} lang=${lang}`);
45
47
  }
@@ -44,12 +44,12 @@ class CryptoKeyUtil {
44
44
  modulusLength: modulus_length,
45
45
  publicKeyEncoding: {
46
46
  type: "spki",
47
- format: "pem"
47
+ format: "pem",
48
48
  },
49
49
  privateKeyEncoding: {
50
50
  type: "pkcs8",
51
- format: "pem"
52
- }
51
+ format: "pem",
52
+ },
53
53
  });
54
54
  return { public_key, private_key };
55
55
  }
@@ -61,12 +61,12 @@ class CryptoKeyUtil {
61
61
  namedCurve: named_curve,
62
62
  publicKeyEncoding: {
63
63
  type: "spki",
64
- format: "pem"
64
+ format: "pem",
65
65
  },
66
66
  privateKeyEncoding: {
67
67
  type: "pkcs8",
68
- format: "pem"
69
- }
68
+ format: "pem",
69
+ },
70
70
  });
71
71
  return { public_key, private_key };
72
72
  }
@@ -92,7 +92,7 @@ class CryptoKeyUtil {
92
92
  const buffer = Buffer.from(payload, "utf8");
93
93
  const encrypted = (0, crypto_1.publicEncrypt)({
94
94
  key: public_key,
95
- padding: crypto_1.default.constants.RSA_PKCS1_OAEP_PADDING
95
+ padding: crypto_1.default.constants.RSA_PKCS1_OAEP_PADDING,
96
96
  }, buffer);
97
97
  return encrypted.toString(output_encoding);
98
98
  }
@@ -100,7 +100,7 @@ class CryptoKeyUtil {
100
100
  const buffer = Buffer.from(encrypted_payload, input_encoding);
101
101
  const decrypted = (0, crypto_1.privateDecrypt)({
102
102
  key: private_key,
103
- padding: crypto_1.default.constants.RSA_PKCS1_OAEP_PADDING
103
+ padding: crypto_1.default.constants.RSA_PKCS1_OAEP_PADDING,
104
104
  }, buffer);
105
105
  return decrypted.toString("utf8");
106
106
  }
@@ -120,8 +120,7 @@ class CryptoKeyUtil {
120
120
  HELPER: PEM VALIDATION
121
121
  ============================================================ */
122
122
  static isValidPEM(key) {
123
- return (key.includes("-----BEGIN") &&
124
- key.includes("-----END"));
123
+ return key.includes("-----BEGIN") && key.includes("-----END");
125
124
  }
126
125
  }
127
126
  exports.default = CryptoKeyUtil;
@@ -24,21 +24,28 @@ class EncryptorDecryptorUtil {
24
24
  this.encrypt_secret_key = this.setEncryptSecretKey(encrypt_secret_key);
25
25
  this.corpus_shift_key = this.env_manger.getEnvVar("CORPUS_SHIFT_KEY", 4) || 4;
26
26
  this.jwt_secret_key = this.env_manger.getEnvVar("JWT_SECRET_KEY", "");
27
- if (!this.encrypt_secret_key ||
28
- !this.jwt_secret_key) {
27
+ if (!this.encrypt_secret_key || !this.jwt_secret_key) {
29
28
  const msg = `Secret Key Variables are missing please set in envrionment variable`;
30
- const data = { encrypt_secret_key: this.encrypt_secret_key, jwt_secret_key: this.jwt_secret_key };
29
+ const data = {
30
+ encrypt_secret_key: this.encrypt_secret_key,
31
+ jwt_secret_key: this.jwt_secret_key,
32
+ };
31
33
  this.logger.error(msg, { data });
32
34
  throw new Error(msg);
33
35
  }
34
36
  }
35
37
  verifyJWT(jwt_string, secret_key, ignore_expiration = false) {
36
38
  try {
37
- const jwt_data = jsonwebtoken_1.default.verify(jwt_string, secret_key, { ignoreExpiration: ignore_expiration });
39
+ const jwt_data = jsonwebtoken_1.default.verify(jwt_string, secret_key, {
40
+ ignoreExpiration: ignore_expiration,
41
+ });
38
42
  return jwt_data;
39
43
  }
40
44
  catch (error) {
41
- this.logger.error(`[${this.name}] JWT string has expired`, { jwt_string, ignore_expiration });
45
+ this.logger.error(`[${this.name}] JWT string has expired`, {
46
+ jwt_string,
47
+ ignore_expiration,
48
+ });
42
49
  return null;
43
50
  }
44
51
  }
@@ -135,8 +142,8 @@ class EncryptorDecryptorUtil {
135
142
  for (const char of array_input_data) {
136
143
  const index = this.corpus.indexOf(char);
137
144
  if (index !== -1) {
138
- const calc_shift = (index - this.corpus_shift_key);
139
- const new_index = calc_shift < 0 ? (this.corpus.length + calc_shift) : calc_shift;
145
+ const calc_shift = index - this.corpus_shift_key;
146
+ const new_index = calc_shift < 0 ? this.corpus.length + calc_shift : calc_shift;
140
147
  decrypted_data += this.corpus[new_index];
141
148
  }
142
149
  else {
@@ -207,11 +214,14 @@ class EncryptorDecryptorUtil {
207
214
  if (!decompressed_data) {
208
215
  return null;
209
216
  }
210
- const decoded_data = (this.decryptV2(decompressed_data));
217
+ const decoded_data = this.decryptV2(decompressed_data);
211
218
  return decoded_data || null;
212
219
  }
213
220
  catch (error) {
214
- this.logger.error(`[${this.name}] Failed to convert encrypted string to data`, { encrypted_string, error });
221
+ this.logger.error(`[${this.name}] Failed to convert encrypted string to data`, {
222
+ encrypted_string,
223
+ error,
224
+ });
215
225
  return null;
216
226
  }
217
227
  }
@@ -7,6 +7,7 @@ declare class EnvManagerUtil {
7
7
  private readonly logger;
8
8
  env_data: EnvConfigInterface;
9
9
  private constructor();
10
+ private resolveEnvFilePath;
10
11
  private getEnvFileName;
11
12
  static getInstance(env_var_options?: EnvVarConfigOptions): EnvManagerUtil;
12
13
  private readENVData;
@@ -19,10 +19,18 @@ class EnvManagerUtil {
19
19
  // 🔒 Private constructor
20
20
  constructor(env_var_options) {
21
21
  this.env_file_name = this.getEnvFileName(env_var_options);
22
- this.yaml_env_file_path = path_1.default.join(constants_1.ENV_VAR_DIR, this.env_file_name);
22
+ this.yaml_env_file_path = this.resolveEnvFilePath(this.env_file_name);
23
23
  this.logger = new logger_util_1.default(this.name);
24
24
  this.env_data = this.readENVData();
25
25
  }
26
+ resolveEnvFilePath(env_file_name) {
27
+ const preferred_path = path_1.default.join(constants_1.ENV_VAR_DIR, env_file_name);
28
+ const legacy_path = path_1.default.join(constants_1.LEGACY_ENV_VAR_DIR, env_file_name);
29
+ if (!fs_1.default.existsSync(preferred_path) && fs_1.default.existsSync(legacy_path)) {
30
+ return legacy_path;
31
+ }
32
+ return preferred_path;
33
+ }
26
34
  // Method to get env file name
27
35
  getEnvFileName(env_var_options) {
28
36
  if (process?.env?.MODE === "development") {
@@ -60,7 +68,7 @@ class EnvManagerUtil {
60
68
  return {};
61
69
  }
62
70
  }
63
- // Get env var from YAML → process.env → default
71
+ // Get env var from YAML → process.env → default
64
72
  getEnvVar(key, default_value) {
65
73
  if (key in this.env_data) {
66
74
  return this.env_data[key];
@@ -60,7 +60,7 @@ class FSActionUtil {
60
60
  if (!exists)
61
61
  return;
62
62
  const entries = await fs_1.promises.readdir(dir_path);
63
- await Promise.all(entries.map(entry => fs_1.promises.rm(path_1.default.join(dir_path, entry), {
63
+ await Promise.all(entries.map((entry) => fs_1.promises.rm(path_1.default.join(dir_path, entry), {
64
64
  recursive: true,
65
65
  force: true,
66
66
  })));
@@ -22,9 +22,7 @@ class InputTransformerUtil {
22
22
  * Capitalize the first letter of a string
23
23
  */
24
24
  static capitalize(input) {
25
- return input
26
- ? input.charAt(0).toUpperCase() + input.slice(1).toLowerCase()
27
- : input;
25
+ return input ? input.charAt(0).toUpperCase() + input.slice(1).toLowerCase() : input;
28
26
  }
29
27
  /**
30
28
  * Capitalize the first letter of each word in a string
@@ -65,9 +63,7 @@ class InputTransformerUtil {
65
63
  if (!amount) {
66
64
  return "0";
67
65
  }
68
- return amount > 0
69
- ? Intl.NumberFormat("en-US").format(amount)
70
- : amount.toString();
66
+ return amount > 0 ? Intl.NumberFormat("en-US").format(amount) : amount.toString();
71
67
  }
72
68
  /**
73
69
  * Format large numbers with suffixes (K, M, B, T)
@@ -105,9 +101,7 @@ class InputTransformerUtil {
105
101
  */
106
102
  static async ipAddressToLocation(ip_address = null) {
107
103
  try {
108
- const suffix = !ip_address || ip_address === "::1"
109
- ? "s"
110
- : `?ip=${ip_address}`;
104
+ const suffix = !ip_address || ip_address === "::1" ? "s" : `?ip=${ip_address}`;
111
105
  const response = await axios_1.default.get(`https://ip2c.org/${suffix}`);
112
106
  const response_text = response.data.toString();
113
107
  if (response_text[0] === "1") {
@@ -130,8 +124,7 @@ class InputTransformerUtil {
130
124
  let age = today.getFullYear() - dob_date.getFullYear();
131
125
  const month_difference = today.getMonth() - dob_date.getMonth();
132
126
  if (month_difference < 0 ||
133
- (month_difference === 0 &&
134
- today.getDate() < dob_date.getDate())) {
127
+ (month_difference === 0 && today.getDate() < dob_date.getDate())) {
135
128
  age--;
136
129
  }
137
130
  return age;
@@ -188,8 +181,7 @@ class InputTransformerUtil {
188
181
  const parts = snake_str.split("_");
189
182
  const last_word = parts.pop();
190
183
  let plural_word;
191
- if (last_word.endsWith("y") &&
192
- !/[aeiou]y$/.test(last_word)) {
184
+ if (last_word.endsWith("y") && !/[aeiou]y$/.test(last_word)) {
193
185
  plural_word = last_word.slice(0, -1) + "ies";
194
186
  }
195
187
  else if (["s", "x", "z"].includes(last_word.slice(-1)) ||
@@ -281,12 +273,10 @@ class InputTransformerUtil {
281
273
  if (old_value == new_value) {
282
274
  continue;
283
275
  }
284
- const formatted_old = typeof old_value === "object" &&
285
- old_value !== null
276
+ const formatted_old = typeof old_value === "object" && old_value !== null
286
277
  ? JSON.stringify(old_value)
287
278
  : String(old_value ?? "null");
288
- const formatted_new = typeof new_value === "object" &&
289
- new_value !== null
279
+ const formatted_new = typeof new_value === "object" && new_value !== null
290
280
  ? JSON.stringify(new_value)
291
281
  : String(new_value ?? "null");
292
282
  structured_diff[key] = {
@@ -298,8 +288,7 @@ class InputTransformerUtil {
298
288
  .map(([key, value]) => `${key} changed from '${value.old}' → '${value.new}'`)
299
289
  .join("; ");
300
290
  return {
301
- readable: readable_changes ||
302
- "No significant changes detected",
291
+ readable: readable_changes || "No significant changes detected",
303
292
  structured: structured_diff,
304
293
  };
305
294
  }
@@ -309,9 +298,7 @@ class InputTransformerUtil {
309
298
  static formatLinksObject(links) {
310
299
  const formatted_links = {};
311
300
  for (const [key, value] of Object.entries(links)) {
312
- const normalized_key = key
313
- .toLowerCase()
314
- .endsWith("_link")
301
+ const normalized_key = key.toLowerCase().endsWith("_link")
315
302
  ? key.toLowerCase()
316
303
  : `${key.toLowerCase()}_link`;
317
304
  formatted_links[normalized_key] = value;
@@ -327,8 +314,7 @@ class InputTransformerUtil {
327
314
  for (let i = 0; i < parts.length; i++) {
328
315
  const key = parts[i];
329
316
  if (!current[key]) {
330
- current[key] =
331
- i === parts.length - 1 ? "string" : {};
317
+ current[key] = i === parts.length - 1 ? "string" : {};
332
318
  }
333
319
  current = current[key];
334
320
  }
@@ -362,7 +348,7 @@ class InputTransformerUtil {
362
348
  // Ensure parts is always a flat array of strings
363
349
  const flat_parts = Array.isArray(parts) ? parts : [parts];
364
350
  // Filter out empty/null/undefined strings to avoid extra separators
365
- const valid_parts = flat_parts.filter(part => part !== null && part !== undefined && part !== "");
351
+ const valid_parts = flat_parts.filter((part) => part !== null && part !== undefined && part !== "");
366
352
  return valid_parts.join(separator);
367
353
  }
368
354
  }
@@ -10,7 +10,7 @@ declare class InputValidatorUtil {
10
10
  private static readonly text_area_regex_reg_exp;
11
11
  private static readonly uuid_regex_reg_exp;
12
12
  private static readonly custom_uuid_regex_reg_exp;
13
- private static readonly env_manager;
13
+ private static get env_manager();
14
14
  static isValidateIn: (value: any, allowed: any[]) => boolean;
15
15
  /** ✅ Check member roles */
16
16
  static isAdmin(name: string): boolean;
@@ -22,23 +22,53 @@ class InputValidatorUtil {
22
22
  static text_area_regex_reg_exp = /^(?=.*[a-zA-Z])[\p{L}\p{N}\p{P}\p{Zs}–—“”‘’]*$/u;
23
23
  static uuid_regex_reg_exp = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
24
24
  static custom_uuid_regex_reg_exp = /^[A-Z0-9]{12}-[A-Z0-9]{12}-[A-Z0-9]{12}-[A-Z0-9]{12}$/;
25
- static env_manager = env_manager_util_1.default.getInstance();
25
+ static get env_manager() {
26
+ return env_manager_util_1.default.getInstance();
27
+ }
26
28
  static isValidateIn = (value, allowed) => allowed.includes(value);
27
29
  /** ✅ Check member roles */
28
- static isAdmin(name) { return ["SuperAdmin", "AdminI", "AdminT"].includes(name); }
29
- static isSuperAdmin(name) { return name === "SuperAdmin"; }
30
- static isLowerSnakeCase(str) { return /^[a-z]+(_[a-z]+)*$/.test(str); }
31
- static isUpperPascalCase(str) { return /^[A-Z][a-zA-Z]*$/.test(str); }
32
- static isEmpty(input) { return !input || input.toString().trim() === ""; }
33
- static isValidOptionalField(str) { return this.optional_field_regex.test(str); }
34
- static isValidName(name) { return this.name_regex_reg_exp.test(name); }
35
- static isValidNamey(name) { return this.namey_regex_reg_exp.test(name); }
36
- static isValidEmail(email) { return this.email_regex_reg_exp.test(email) && email.length <= 254; }
37
- static isValidPhoneNumber(tel) { return this.tel_regex_reg_exp.test(tel); }
38
- static isValidPassword(password) { return this.pass_regex_reg_exp.test(password); }
39
- static isDigit(input) { return typeof input === "number" || !isNaN(Number(input)); }
40
- static isValidInteger(input) { return Number.isInteger(input) && input > 0; }
41
- static isValidFloat(input) { return !isNaN(Number(input)) && parseFloat(input) > 0; }
30
+ static isAdmin(name) {
31
+ return ["SuperAdmin", "AdminI", "AdminT"].includes(name);
32
+ }
33
+ static isSuperAdmin(name) {
34
+ return name === "SuperAdmin";
35
+ }
36
+ static isLowerSnakeCase(str) {
37
+ return /^[a-z]+(_[a-z]+)*$/.test(str);
38
+ }
39
+ static isUpperPascalCase(str) {
40
+ return /^[A-Z][a-zA-Z]*$/.test(str);
41
+ }
42
+ static isEmpty(input) {
43
+ return !input || input.toString().trim() === "";
44
+ }
45
+ static isValidOptionalField(str) {
46
+ return this.optional_field_regex.test(str);
47
+ }
48
+ static isValidName(name) {
49
+ return this.name_regex_reg_exp.test(name);
50
+ }
51
+ static isValidNamey(name) {
52
+ return this.namey_regex_reg_exp.test(name);
53
+ }
54
+ static isValidEmail(email) {
55
+ return this.email_regex_reg_exp.test(email) && email.length <= 254;
56
+ }
57
+ static isValidPhoneNumber(tel) {
58
+ return this.tel_regex_reg_exp.test(tel);
59
+ }
60
+ static isValidPassword(password) {
61
+ return this.pass_regex_reg_exp.test(password);
62
+ }
63
+ static isDigit(input) {
64
+ return typeof input === "number" || !isNaN(Number(input));
65
+ }
66
+ static isValidInteger(input) {
67
+ return Number.isInteger(input) && input > 0;
68
+ }
69
+ static isValidFloat(input) {
70
+ return !isNaN(Number(input)) && parseFloat(input) > 0;
71
+ }
42
72
  static isValidURLY(url) {
43
73
  try {
44
74
  new URL(url);
@@ -48,8 +78,12 @@ class InputValidatorUtil {
48
78
  return false;
49
79
  }
50
80
  }
51
- static isValidURL(url) { return this.url_regex_reg_exp.test(url) && this.isValidURLY(url); }
52
- static isBoolean(value) { return typeof value === "boolean" || ["1", "0"].includes(String(value)); }
81
+ static isValidURL(url) {
82
+ return this.url_regex_reg_exp.test(url) && this.isValidURLY(url);
83
+ }
84
+ static isBoolean(value) {
85
+ return typeof value === "boolean" || ["1", "0"].includes(String(value));
86
+ }
53
87
  static isValidLongText(text) {
54
88
  if (!text || typeof text !== "string") {
55
89
  return false;
@@ -60,9 +94,15 @@ class InputValidatorUtil {
60
94
  }
61
95
  return this.text_area_regex_reg_exp.test(text.trim());
62
96
  }
63
- static isValidUUID(uuid) { return this.uuid_regex_reg_exp.test(uuid); }
64
- static isValidCustomUUID(uuid) { return this.custom_uuid_regex_reg_exp.test(uuid); }
65
- static isArrayUnique(arr) { return new Set(arr).size === arr.length; }
97
+ static isValidUUID(uuid) {
98
+ return this.uuid_regex_reg_exp.test(uuid);
99
+ }
100
+ static isValidCustomUUID(uuid) {
101
+ return this.custom_uuid_regex_reg_exp.test(uuid);
102
+ }
103
+ static isArrayUnique(arr) {
104
+ return new Set(arr).size === arr.length;
105
+ }
66
106
  static isValidFutureDate(date_string) {
67
107
  const date = (0, dayjs_1.default)(date_string);
68
108
  return date.isValid() && date.isAfter((0, dayjs_1.default)());
@@ -87,10 +127,18 @@ class InputValidatorUtil {
87
127
  return await bcrypt_1.default.compare(password, hash_password);
88
128
  }
89
129
  /** ✅ Check environment */
90
- static isProduction() { return InputValidatorUtil?.env_manager?.env_data?.MODE === "production"; }
91
- static isStaging() { return InputValidatorUtil?.env_manager?.env_data?.MODE === "staging"; }
92
- static isDevelopment() { return InputValidatorUtil?.env_manager?.env_data?.MODE === "development"; }
93
- static isLive() { return ["production", "staging"].includes(InputValidatorUtil?.env_manager?.env_data?.MODE || ""); }
130
+ static isProduction() {
131
+ return InputValidatorUtil?.env_manager?.env_data?.MODE === "production";
132
+ }
133
+ static isStaging() {
134
+ return InputValidatorUtil?.env_manager?.env_data?.MODE === "staging";
135
+ }
136
+ static isDevelopment() {
137
+ return InputValidatorUtil?.env_manager?.env_data?.MODE === "development";
138
+ }
139
+ static isLive() {
140
+ return ["production", "staging"].includes(InputValidatorUtil?.env_manager?.env_data?.MODE || "");
141
+ }
94
142
  /** ✅ Validate ReCaptcha */
95
143
  static async isValidReCaptcha(recpatcha_token) {
96
144
  const { RECAPTCHA_SECRET_KEY, RECPATHA_VERIFY_URL } = InputValidatorUtil?.env_manager?.env_data;
@@ -113,7 +161,7 @@ class InputValidatorUtil {
113
161
  return exist;
114
162
  }
115
163
  if (!exist) {
116
- fs_1.default.mkdirSync(directory);
164
+ fs_1.default.mkdirSync(directory, { recursive: true });
117
165
  }
118
166
  return return_dir_path ? directory : true;
119
167
  }
@@ -189,8 +237,8 @@ class InputValidatorUtil {
189
237
  };
190
238
  // Utility to get nested value by dot notation
191
239
  const getNestedValue = (obj, path) => {
192
- return path.split('.').reduce((acc, part) => {
193
- if (acc && typeof acc === 'object' && part in acc) {
240
+ return path.split(".").reduce((acc, part) => {
241
+ if (acc && typeof acc === "object" && part in acc) {
194
242
  return acc[part];
195
243
  }
196
244
  return undefined;
@@ -10,12 +10,12 @@ declare class LoggerUtil {
10
10
  * Ensures a directory exists. If it doesn't, creates it.
11
11
  * @param directory_path - Path to the directory
12
12
  * @returns The absolute path of the ensured directory
13
- */
13
+ */
14
14
  private ensureDirExists;
15
15
  /**
16
16
  * Generate log unique log file name with timestamp and module name
17
17
  * @returns The absolute path of the module log file
18
- */
18
+ */
19
19
  private getLogFilePath;
20
20
  private safeStringify;
21
21
  private log;