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
@@ -6,7 +6,7 @@ const indentBlock = (code, level) => {
6
6
  const indentation = INDENT.repeat(level);
7
7
  return code
8
8
  .split("\n")
9
- .map(line => line.trim().length ? indentation + line : line)
9
+ .map((line) => (line.trim().length ? indentation + line : line))
10
10
  .join("\n");
11
11
  };
12
12
  const serializeSequelizeDataType = (type) => {
@@ -54,8 +54,8 @@ const serializeIndexDefinition = (index) => {
54
54
  delete clone.fields;
55
55
  delete clone.comment;
56
56
  const entries = Object.entries(clone)
57
- .map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
58
- .join(",\n");
57
+ .map(([key, value]) => `${key}: ${JSON.stringify(value)},`)
58
+ .join("\n");
59
59
  return entries;
60
60
  };
61
61
  const serializeSequelizeColumnsObject = (columns) => {
@@ -71,13 +71,15 @@ ${indentBlock("}", 3)}
71
71
  `;
72
72
  };
73
73
  const serializeSequelizeIndexesArray = (indexes) => {
74
- return indexes.map(index => {
74
+ return indexes
75
+ .map((index) => {
75
76
  return `{
76
77
  name: "${index.name}",
77
78
  fields: ${JSON.stringify(index.fields)},
78
79
  ${serializeIndexDefinition(index).replace(/^{|}$/g, "")}
79
80
  }`;
80
- }).join(",\n ");
81
+ })
82
+ .join(",\n ");
81
83
  };
82
84
  const SEQUELIZE_SCHEMA_CODE_TEMPLATE = (schema_name, table_name, model_name, migration_priority) => {
83
85
  return `
@@ -138,25 +140,29 @@ class Create${schema_model_name}TableMigration {
138
140
 
139
141
  constructor() {}
140
142
 
141
- public async up(queryInterface: QueryInterface, Sequelize: Sequelize) {
143
+ public async up(queryInterface: QueryInterface, Sequelize: Sequelize, migration_options: any = {}) {
142
144
  try {
143
145
  const table_name = "${schema_table_name}";
144
146
 
145
147
  await queryInterface.createTable(
146
148
  table_name,
147
- ${indentBlock(rendered_columns, 1)}
149
+ ${indentBlock(rendered_columns, 1)},
150
+ migration_options
148
151
  );
149
152
 
150
- ${schema_definition.indexes?.map(index => `
153
+ ${schema_definition.indexes
154
+ ?.map((index) => `
151
155
  await queryInterface.addIndex(
152
156
  table_name,
153
157
  ${JSON.stringify(index.fields)},
154
158
  {
155
159
  name: "${index.name}",
156
160
  ${indentBlock(serializeIndexDefinition(index), 1)}
161
+ ...migration_options,
157
162
  }
158
163
  );
159
- `).join("")}
164
+ `)
165
+ .join("")}
160
166
 
161
167
  this.logger.success(\`✅ Table "\${table_name}" created successfully.\`);
162
168
  }
@@ -166,9 +172,9 @@ class Create${schema_model_name}TableMigration {
166
172
  }
167
173
  }
168
174
 
169
- public async down(queryInterface: QueryInterface, Sequelize: Sequelize) {
175
+ public async down(queryInterface: QueryInterface, Sequelize: Sequelize, migration_options: any = {}) {
170
176
  try {
171
- await queryInterface.dropTable("${schema_table_name}");
177
+ await queryInterface.dropTable("${schema_table_name}", migration_options);
172
178
  this.logger.success(\`🗑️ Table "${schema_table_name}" dropped successfully.\`);
173
179
  } catch (error: any) {
174
180
  this.logger.error(\`🚫 Rollback failed: "\${error.message}"\`, { error });
@@ -192,66 +198,85 @@ class Update${model_name}TableMigration {
192
198
 
193
199
  constructor() {}
194
200
 
195
- public async up(queryInterface: QueryInterface, Sequelize: Sequelize) {
201
+ public async up(queryInterface: QueryInterface, Sequelize: Sequelize, migration_options: any = {}) {
196
202
  try {
197
203
  let table_name = "${table_name}";
198
204
 
199
- ${diff.table_renamed ? `
205
+ ${diff.table_renamed
206
+ ? `
200
207
  await queryInterface.renameTable(
201
208
  "${diff.table_renamed.from}",
202
- "${diff.table_renamed.to}"
209
+ "${diff.table_renamed.to}",
210
+ migration_options
203
211
  );
204
212
  table_name = "${diff.table_renamed.to}";
205
- ` : ""}
213
+ `
214
+ : ""}
206
215
 
207
216
  // ----------- ADD COLUMNS -----------
208
- ${diff.columns.added.map(col => `
217
+ ${diff.columns.added
218
+ .map((col) => `
209
219
  await queryInterface.addColumn(
210
220
  table_name,
211
221
  "${col}",
212
- ${indentBlock(serializeSequelizeColumnDefinition(current_schema.columns[col]), 1)}
222
+ ${indentBlock(serializeSequelizeColumnDefinition(current_schema.columns[col]), 1)},
223
+ migration_options
213
224
  );
214
- `).join("")}
225
+ `)
226
+ .join("")}
215
227
 
216
228
  // ----------- MODIFY COLUMNS -----------
217
- ${diff.columns.modified.map(col => `
229
+ ${diff.columns.modified
230
+ .map((col) => `
218
231
  await queryInterface.changeColumn(
219
232
  table_name,
220
233
  "${col}",
221
- ${indentBlock(serializeSequelizeColumnDefinition(current_schema.columns[col]), 1)}
234
+ ${indentBlock(serializeSequelizeColumnDefinition(current_schema.columns[col]), 1)},
235
+ migration_options
222
236
  );
223
- `).join("")}
237
+ `)
238
+ .join("")}
224
239
 
225
240
  // ----------- REMOVE COLUMNS -----------
226
- ${diff.columns.removed.map(col => `
241
+ ${diff.columns.removed
242
+ .map((col) => `
227
243
  await queryInterface.removeColumn(
228
244
  table_name,
229
- "${col}"
245
+ "${col}",
246
+ migration_options
230
247
  );
231
- `).join("")}
248
+ `)
249
+ .join("")}
232
250
 
233
251
  // ----------- ADD INDEXES -----------
234
- ${diff.indexes.added.map(name => {
252
+ ${diff.indexes.added
253
+ .map((name) => {
235
254
  const curr_indxs = current_schema?.indexes || [];
236
- const idx = curr_indxs.find(i => i.name === name);
237
- return idx ? `
255
+ const idx = curr_indxs.find((i) => i.name === name);
256
+ return idx
257
+ ? `
238
258
  await queryInterface.addIndex(
239
259
  table_name,
240
260
  ${JSON.stringify(idx.fields)},
241
261
  {
242
262
  name: "${idx.name}",
243
263
  ${indentBlock(serializeIndexDefinition(idx).replace(/^{|}$/g, ""), 1)}
264
+ ...migration_options,
244
265
  }
245
266
  );
246
- ` : "";
247
- }).join("")}
267
+ `
268
+ : "";
269
+ })
270
+ .join("")}
248
271
 
249
272
  // ----------- MODIFY INDEXES -----------
250
- ${diff.indexes.modified.map(name => {
273
+ ${diff.indexes.modified
274
+ .map((name) => {
251
275
  const curr_indxs = current_schema?.indexes || [];
252
- const idx = curr_indxs.find(i => i.name === name);
253
- return idx ? `
254
- await queryInterface.removeIndex(table_name, "${name}");
276
+ const idx = curr_indxs.find((i) => i.name === name);
277
+ return idx
278
+ ? `
279
+ await queryInterface.removeIndex(table_name, "${name}", migration_options);
255
280
 
256
281
  await queryInterface.addIndex(
257
282
  table_name,
@@ -259,15 +284,20 @@ class Update${model_name}TableMigration {
259
284
  {
260
285
  name: "${idx.name}",
261
286
  ${indentBlock(serializeIndexDefinition(idx).replace(/^{|}$/g, ""), 1)}
287
+ ...migration_options,
262
288
  }
263
289
  );
264
- ` : "";
265
- }).join("")}
290
+ `
291
+ : "";
292
+ })
293
+ .join("")}
266
294
 
267
295
  // ----------- REMOVE INDEXES -----------
268
- ${diff.indexes.removed.map(name => `
269
- await queryInterface.removeIndex(table_name, "${name}");
270
- `).join("")}
296
+ ${diff.indexes.removed
297
+ .map((name) => `
298
+ await queryInterface.removeIndex(table_name, "${name}", migration_options);
299
+ `)
300
+ .join("")}
271
301
 
272
302
  this.logger.success(\`✅ Table "\${table_name}" updated successfully.\`);
273
303
  }
@@ -277,20 +307,24 @@ class Update${model_name}TableMigration {
277
307
  }
278
308
  }
279
309
 
280
- public async down(queryInterface: QueryInterface, Sequelize: Sequelize) {
310
+ public async down(queryInterface: QueryInterface, Sequelize: Sequelize, migration_options: any = {}) {
281
311
  try {
282
312
  let table_name = "${table_name}";
283
313
 
284
314
  // ----------- REVERT INDEXES -----------
285
- ${diff.indexes.added.map(name => `
286
- await queryInterface.removeIndex(table_name, "${name}");
287
- `).join("")}
288
-
289
- ${diff.indexes.modified.map(name => {
315
+ ${diff.indexes.added
316
+ .map((name) => `
317
+ await queryInterface.removeIndex(table_name, "${name}", migration_options);
318
+ `)
319
+ .join("")}
320
+
321
+ ${diff.indexes.modified
322
+ .map((name) => {
290
323
  const prev_indxs = previous_schema?.indexes || [];
291
- const idx = prev_indxs.find(i => i.name === name);
292
- return idx ? `
293
- await queryInterface.removeIndex(table_name, "${name}");
324
+ const idx = prev_indxs.find((i) => i.name === name);
325
+ return idx
326
+ ? `
327
+ await queryInterface.removeIndex(table_name, "${name}", migration_options);
294
328
 
295
329
  await queryInterface.addIndex(
296
330
  table_name,
@@ -298,53 +332,72 @@ class Update${model_name}TableMigration {
298
332
  {
299
333
  name: "${idx.name}",
300
334
  ${indentBlock(serializeIndexDefinition(idx).replace(/^{|}$/g, ""), 1)}
335
+ ...migration_options,
301
336
  }
302
337
  );
303
- ` : "";
304
- }).join("")}
338
+ `
339
+ : "";
340
+ })
341
+ .join("")}
305
342
 
306
- ${diff.indexes.removed.map(name => {
343
+ ${diff.indexes.removed
344
+ .map((name) => {
307
345
  const prev_indxs = previous_schema?.indexes || [];
308
- const idx = prev_indxs.find(i => i.name === name);
309
- return idx ? `
346
+ const idx = prev_indxs.find((i) => i.name === name);
347
+ return idx
348
+ ? `
310
349
  await queryInterface.addIndex(
311
350
  table_name,
312
351
  ${JSON.stringify(idx.fields)},
313
352
  {
314
353
  name: "${idx.name}",
315
354
  ${indentBlock(serializeIndexDefinition(idx).replace(/^{|}$/g, ""), 1)}
355
+ ...migration_options,
316
356
  }
317
357
  );
318
- ` : "";
319
- }).join("")}
358
+ `
359
+ : "";
360
+ })
361
+ .join("")}
320
362
 
321
363
  // ----------- REVERT COLUMNS -----------
322
- ${diff.columns.modified.map(col => `
364
+ ${diff.columns.modified
365
+ .map((col) => `
323
366
  await queryInterface.changeColumn(
324
367
  table_name,
325
368
  "${col}",
326
- ${indentBlock(serializeSequelizeColumnDefinition(previous_schema.columns[col]), 1)}
369
+ ${indentBlock(serializeSequelizeColumnDefinition(previous_schema.columns[col]), 1)},
370
+ migration_options
327
371
  );
328
- `).join("")}
372
+ `)
373
+ .join("")}
329
374
 
330
- ${diff.columns.added.map(col => `
331
- await queryInterface.removeColumn(table_name, "${col}");
332
- `).join("")}
375
+ ${diff.columns.added
376
+ .map((col) => `
377
+ await queryInterface.removeColumn(table_name, "${col}", migration_options);
378
+ `)
379
+ .join("")}
333
380
 
334
- ${diff.columns.removed.map(col => `
381
+ ${diff.columns.removed
382
+ .map((col) => `
335
383
  await queryInterface.addColumn(
336
384
  table_name,
337
385
  "${col}",
338
- ${indentBlock(serializeSequelizeColumnDefinition(previous_schema.columns[col]), 1)}
386
+ ${indentBlock(serializeSequelizeColumnDefinition(previous_schema.columns[col]), 1)},
387
+ migration_options
339
388
  );
340
- `).join("")}
389
+ `)
390
+ .join("")}
341
391
 
342
- ${diff.table_renamed ? `
392
+ ${diff.table_renamed
393
+ ? `
343
394
  await queryInterface.renameTable(
344
395
  "${diff.table_renamed.to}",
345
- "${diff.table_renamed.from}"
396
+ "${diff.table_renamed.from}",
397
+ migration_options
346
398
  );
347
- ` : ""}
399
+ `
400
+ : ""}
348
401
 
349
402
  this.logger.success(\`🗑️ Rollback completed successfully.\`);
350
403
  }
@@ -369,29 +422,29 @@ class ${class_name}Seeder {
369
422
  /**
370
423
  * Seed method
371
424
  */
372
- public async up(queryInterface: QueryInterface): Promise<void> {
425
+ public async up(queryInterface: QueryInterface, Sequelize?: unknown, seeder_options: any = {}): Promise<void> {
373
426
  const seed_data = this.getSeedData();
374
427
 
375
428
  if (!seed_data || seed_data.length === 0) {
376
429
  throw new Error("❌ Seeder data for '${table_name.toLowerCase()}' is empty. Aborting bulk insert.");
377
430
  }
378
431
 
379
- await queryInterface.bulkInsert('${table_name.toLowerCase()}', seed_data);
432
+ await queryInterface.bulkInsert('${table_name.toLowerCase()}', seed_data, seeder_options);
380
433
  }
381
434
 
382
435
  /**
383
436
  * Undo seed method
384
437
  */
385
- public async down(queryInterface: QueryInterface): Promise<void> {
438
+ public async down(queryInterface: QueryInterface, Sequelize?: unknown, seeder_options: any = {}): Promise<void> {
386
439
  const seed_data = this.getSeedData();
387
440
 
388
441
  if (!seed_data || seed_data.length === 0) {
389
- throw new Error("❌ Seeder data for ${table_name.toLowerCase()}' is empty. Nothing to delete.");
442
+ throw new Error("❌ Seeder data for '${table_name.toLowerCase()}' is empty. Nothing to delete.");
390
443
  }
391
444
 
392
445
  const ids = seed_data.map(row => row.id);
393
446
 
394
- await queryInterface.bulkDelete('${table_name.toLowerCase()}', { id: ids });
447
+ await queryInterface.bulkDelete('${table_name.toLowerCase()}', { id: ids }, seeder_options);
395
448
  }
396
449
 
397
450
  /**
@@ -409,7 +462,7 @@ export default ${class_name}Seeder;
409
462
  exports.SEQUELIZE_SEEDER_TEMPLATE = SEQUELIZE_SEEDER_TEMPLATE;
410
463
  const SEQUELIZE_MODEL_CODE_TEMPLATE = (schema_model_name, schema_file_name, schema_columns) => {
411
464
  const attributes = Object.keys(schema_columns)
412
- .map(col => ` declare ${col}: any;`)
465
+ .map((col) => ` declare ${col}: any;`)
413
466
  .join("\n");
414
467
  return `
415
468
  import { Model, Sequelize } from "sequelize";
@@ -510,14 +563,14 @@ for (const register of associationMethods) {
510
563
  // -------------------------
511
564
  // Create named initialized exports
512
565
  // -------------------------
513
- ${model_names.map(m => `const ${m}Model: typeof ${m} = initializedModels["${m}"];`).join("\n")}
566
+ ${model_names.map((m) => `const ${m}Model: typeof ${m} = initializedModels["${m}"];`).join("\n")}
514
567
 
515
568
  // -------------------------
516
569
  // Export raw + initialized
517
570
  // -------------------------
518
571
  export {
519
572
  ${export_raw},
520
- ${model_names.map(m => ` ${m}Model`).join(",\n")}
573
+ ${model_names.map((m) => ` ${m}Model`).join(",\n")}
521
574
  };
522
575
  `;
523
576
  };
@@ -1,6 +1,7 @@
1
1
  export declare const BASE_DIR: string;
2
2
  export declare const LOG_DIR: string;
3
3
  export declare const ENV_VAR_DIR: string;
4
+ export declare const LEGACY_ENV_VAR_DIR: string;
4
5
  export declare const SCHEMAS_DIR: string;
5
6
  export declare const SCHEMA_SNAPSHOTS_DIR: string;
6
7
  export declare const MODELS_DIR: string;
@@ -3,11 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.FILE_UPLOAD_ALLOWED_MIME_TYPES = exports.FILE_UPLOAD_ENV_KEYS = exports.FILE_UPLOAD_LIMITS = exports.DEFAULT_CONTENT_CACHE_TTL = exports.DEFAULT_CONTENT_LANG = exports.DEFAULT_CONTENT_URL = exports.CONTENT_LANG_KEY = exports.CONTENT_URL_KEY = exports.CONTENT_CACHE_TTL_KEY = exports.EMAIL_ENQUEUE_UTIL_FILE_NAME = exports.EMAIL_ENQUEUE_TYPES_FILE_NAME = exports.DEFAULT_MAILER_CACHE_TTL = exports.DEFAULT_MAILER_CACHE_KEY = exports.DEFAULT_RBAC_CACHE_TTL = exports.DEFAULT_RBAC_CACHE_KEY = exports.DEFAULT_TOTP_WINDOW = exports.DEFAULT_TOTP_DIGITS = exports.DEFAULT_TOTP_STEP = exports.ALPHABET_CORPUS = exports.CHARACTER_CORPUS = exports.REQUEST_RATE_LIMITTER_OPTIONS = exports.CORS_MAX_AGE_IN_MICRO_SECONDS = exports.CORS_MAX_AGE_IN_SECONDS = exports.CORS_ALLOWED_HEADERS = exports.HEADERS_KEY_NAME = exports.CORS_ALLOWED_METHODS = exports.DEVICE_ID_HEADERS_NAME = exports.DEVICE_ID_COOKIE_NAME = exports.DEVICE_ID_COOKIE_MAX_AGE = exports.REQUEST_ID_HEADERS_NAME = exports.REQUEST_ID_COOKIE_NAME = exports.REQUEST_ID_COOKIE_MAX_AGE = exports.SEQUELIZE_SEEDER_META_TABLE_NAME = exports.SEQUELIZE_META_TABLE_NAME = exports.EMAIL_PREVIEW_DIR = exports.EMAIL_ENQUEUE_DIR = exports.SEEDERS_DIR = exports.MIGRATIONS_DIR = exports.MODELS_DIR = exports.SCHEMA_SNAPSHOTS_DIR = exports.SCHEMAS_DIR = exports.ENV_VAR_DIR = exports.LOG_DIR = exports.BASE_DIR = void 0;
6
+ exports.FILE_UPLOAD_ALLOWED_MIME_TYPES = exports.FILE_UPLOAD_ENV_KEYS = exports.FILE_UPLOAD_LIMITS = exports.DEFAULT_CONTENT_CACHE_TTL = exports.DEFAULT_CONTENT_LANG = exports.DEFAULT_CONTENT_URL = exports.CONTENT_LANG_KEY = exports.CONTENT_URL_KEY = exports.CONTENT_CACHE_TTL_KEY = exports.EMAIL_ENQUEUE_UTIL_FILE_NAME = exports.EMAIL_ENQUEUE_TYPES_FILE_NAME = exports.DEFAULT_MAILER_CACHE_TTL = exports.DEFAULT_MAILER_CACHE_KEY = exports.DEFAULT_RBAC_CACHE_TTL = exports.DEFAULT_RBAC_CACHE_KEY = exports.DEFAULT_TOTP_WINDOW = exports.DEFAULT_TOTP_DIGITS = exports.DEFAULT_TOTP_STEP = exports.ALPHABET_CORPUS = exports.CHARACTER_CORPUS = exports.REQUEST_RATE_LIMITTER_OPTIONS = exports.CORS_MAX_AGE_IN_MICRO_SECONDS = exports.CORS_MAX_AGE_IN_SECONDS = exports.CORS_ALLOWED_HEADERS = exports.HEADERS_KEY_NAME = exports.CORS_ALLOWED_METHODS = exports.DEVICE_ID_HEADERS_NAME = exports.DEVICE_ID_COOKIE_NAME = exports.DEVICE_ID_COOKIE_MAX_AGE = exports.REQUEST_ID_HEADERS_NAME = exports.REQUEST_ID_COOKIE_NAME = exports.REQUEST_ID_COOKIE_MAX_AGE = exports.SEQUELIZE_SEEDER_META_TABLE_NAME = exports.SEQUELIZE_META_TABLE_NAME = exports.EMAIL_PREVIEW_DIR = exports.EMAIL_ENQUEUE_DIR = exports.SEEDERS_DIR = exports.MIGRATIONS_DIR = exports.MODELS_DIR = exports.SCHEMA_SNAPSHOTS_DIR = exports.SCHEMAS_DIR = exports.LEGACY_ENV_VAR_DIR = exports.ENV_VAR_DIR = exports.LOG_DIR = exports.BASE_DIR = void 0;
7
7
  const path_1 = __importDefault(require("path"));
8
8
  exports.BASE_DIR = process.cwd();
9
9
  exports.LOG_DIR = path_1.default.join(exports.BASE_DIR, "logs");
10
- exports.ENV_VAR_DIR = path_1.default.join(exports.BASE_DIR, "environment_varaiables");
10
+ exports.ENV_VAR_DIR = path_1.default.join(exports.BASE_DIR, "environment_variables");
11
+ exports.LEGACY_ENV_VAR_DIR = path_1.default.join(exports.BASE_DIR, "environment_variables");
11
12
  exports.SCHEMAS_DIR = path_1.default.join(exports.BASE_DIR, "src/database/schemas");
12
13
  exports.SCHEMA_SNAPSHOTS_DIR = path_1.default.join(exports.BASE_DIR, "src/database/schema_snapshots");
13
14
  exports.MODELS_DIR = path_1.default.join(exports.BASE_DIR, "src/database/models");
@@ -17,10 +18,10 @@ exports.EMAIL_ENQUEUE_DIR = path_1.default.join(exports.BASE_DIR, "src/");
17
18
  exports.EMAIL_PREVIEW_DIR = path_1.default.join(exports.BASE_DIR, "local_media/email/email_preview");
18
19
  exports.SEQUELIZE_META_TABLE_NAME = "sequelize_database_tables_meta";
19
20
  exports.SEQUELIZE_SEEDER_META_TABLE_NAME = "sequelize_database_table_seeder_meta";
20
- exports.REQUEST_ID_COOKIE_MAX_AGE = (1000 * 60 * 60 * 24 * 30); // 7 days
21
+ exports.REQUEST_ID_COOKIE_MAX_AGE = 1000 * 60 * 60 * 24 * 30; // 7 days
21
22
  exports.REQUEST_ID_COOKIE_NAME = "request_id";
22
23
  exports.REQUEST_ID_HEADERS_NAME = "X-Request-Id";
23
- exports.DEVICE_ID_COOKIE_MAX_AGE = (1000 * 60 * 60 * 24 * 180); // 180 days
24
+ exports.DEVICE_ID_COOKIE_MAX_AGE = 1000 * 60 * 60 * 24 * 180; // 180 days
24
25
  exports.DEVICE_ID_COOKIE_NAME = "device_id";
25
26
  exports.DEVICE_ID_HEADERS_NAME = "X-Device-Id";
26
27
  // CORS constants
@@ -95,23 +96,89 @@ exports.CORS_ALLOWED_HEADERS = [
95
96
  exports.HEADERS_KEY_NAME.access_control_allow_credentials,
96
97
  exports.HEADERS_KEY_NAME.access_control_max_age,
97
98
  ];
98
- exports.CORS_MAX_AGE_IN_SECONDS = (600); // default: 10 min
99
- exports.CORS_MAX_AGE_IN_MICRO_SECONDS = (1000 * 60 * 10); // 10 minutes
99
+ exports.CORS_MAX_AGE_IN_SECONDS = 600; // default: 10 min
100
+ exports.CORS_MAX_AGE_IN_MICRO_SECONDS = 1000 * 60 * 10; // 10 minutes
100
101
  // Rate limitter
101
102
  exports.REQUEST_RATE_LIMITTER_OPTIONS = {
102
- window_ms: (60 * 1000), // 1 MINS
103
+ window_ms: 60 * 1000, // 1 MINS
103
104
  max_requests: 50,
104
- message: "⏳ Too many requests from this IP, please try again later"
105
+ message: "⏳ Too many requests from this IP, please try again later",
105
106
  };
106
- exports.CHARACTER_CORPUS = ["6", ";", "s", "[", "w", "*", "n", "K", "h", "U", "#", "P", "T", "&", "M", "2", "}", "x", ")", "{", "|", "i", "%", "m", ":", "E", "q", "?", "0", "@", "1", "v", "A", "W", "<", "y", "Y", "4", "5", ".", "e", "G", ",", "D", "7", "I", "j", ">", "g", "t", "k", "c", "V", "9", "J", "L", "u", "H", "b", "Z", "+", '"', "'", "a", "f"];
107
+ exports.CHARACTER_CORPUS = [
108
+ "6",
109
+ ";",
110
+ "s",
111
+ "[",
112
+ "w",
113
+ "*",
114
+ "n",
115
+ "K",
116
+ "h",
117
+ "U",
118
+ "#",
119
+ "P",
120
+ "T",
121
+ "&",
122
+ "M",
123
+ "2",
124
+ "}",
125
+ "x",
126
+ ")",
127
+ "{",
128
+ "|",
129
+ "i",
130
+ "%",
131
+ "m",
132
+ ":",
133
+ "E",
134
+ "q",
135
+ "?",
136
+ "0",
137
+ "@",
138
+ "1",
139
+ "v",
140
+ "A",
141
+ "W",
142
+ "<",
143
+ "y",
144
+ "Y",
145
+ "4",
146
+ "5",
147
+ ".",
148
+ "e",
149
+ "G",
150
+ ",",
151
+ "D",
152
+ "7",
153
+ "I",
154
+ "j",
155
+ ">",
156
+ "g",
157
+ "t",
158
+ "k",
159
+ "c",
160
+ "V",
161
+ "9",
162
+ "J",
163
+ "L",
164
+ "u",
165
+ "H",
166
+ "b",
167
+ "Z",
168
+ "+",
169
+ '"',
170
+ "'",
171
+ "a",
172
+ "f",
173
+ ];
107
174
  exports.ALPHABET_CORPUS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
108
175
  exports.DEFAULT_TOTP_STEP = 30;
109
176
  exports.DEFAULT_TOTP_DIGITS = 6;
110
177
  exports.DEFAULT_TOTP_WINDOW = 1;
111
178
  exports.DEFAULT_RBAC_CACHE_KEY = "RBAC_SNAPSHOT";
112
- exports.DEFAULT_RBAC_CACHE_TTL = (1000 * 60 * 60 * 24); // 24 hours
179
+ exports.DEFAULT_RBAC_CACHE_TTL = 1000 * 60 * 60 * 24; // 24 hours
113
180
  exports.DEFAULT_MAILER_CACHE_KEY = "MAILER_SNAPSHOT";
114
- exports.DEFAULT_MAILER_CACHE_TTL = (1000 * 60 * 60 * 24); // 24 hours
181
+ exports.DEFAULT_MAILER_CACHE_TTL = 1000 * 60 * 60 * 24; // 24 hours
115
182
  exports.EMAIL_ENQUEUE_TYPES_FILE_NAME = "types/email_enqueue_type.generated.ts";
116
183
  exports.EMAIL_ENQUEUE_UTIL_FILE_NAME = "utils/email_enqueue_util.generated.ts";
117
184
  exports.CONTENT_CACHE_TTL_KEY = "CONTENT_CACHE_TTL";
@@ -119,13 +186,13 @@ exports.CONTENT_URL_KEY = "CONTENT_URL";
119
186
  exports.CONTENT_LANG_KEY = "CONTENT_LANG";
120
187
  exports.DEFAULT_CONTENT_URL = "http://localhost:4000/content/{{type}}_content/{{lang}}.json";
121
188
  exports.DEFAULT_CONTENT_LANG = "en-GB";
122
- exports.DEFAULT_CONTENT_CACHE_TTL = (1000 * 60 * 60 * 24); // 24 hours
189
+ exports.DEFAULT_CONTENT_CACHE_TTL = 1000 * 60 * 60 * 24; // 24 hours
123
190
  // src/config/constants.ts
124
191
  // src/config/constants.ts
125
192
  exports.FILE_UPLOAD_LIMITS = {
126
193
  IMAGE_MAX_SIZE: 5 * 1024 * 1024,
127
194
  VIDEO_MAX_SIZE: 50 * 1024 * 1024,
128
- DOCUMENT_MAX_SIZE: 10 * 1024 * 1024
195
+ DOCUMENT_MAX_SIZE: 10 * 1024 * 1024,
129
196
  };
130
197
  exports.FILE_UPLOAD_ENV_KEYS = {
131
198
  IMAGE_MAX_SIZE: "FILE_UPLOAD_IMAGE_MAX_SIZE",
@@ -140,10 +207,10 @@ exports.FILE_UPLOAD_ENV_KEYS = {
140
207
  GCS_BUCKET_NAME: "FILE_UPLOAD_GCS_BUCKET_NAME",
141
208
  GCS_CLIENT_EMAIL: "FILE_UPLOAD_GCS_CLIENT_EMAIL",
142
209
  GCS_PRIVATE_KEY: "FILE_UPLOAD_GCS_PRIVATE_KEY",
143
- STORAGE_DRIVER_NAME: "FILE_UPLOAD_STORAGE_DRIVER_NAME"
210
+ STORAGE_DRIVER_NAME: "FILE_UPLOAD_STORAGE_DRIVER_NAME",
144
211
  };
145
212
  exports.FILE_UPLOAD_ALLOWED_MIME_TYPES = {
146
213
  image: ["image/png", "image/jpeg", "image/webp"],
147
214
  video: ["video/mp4", "video/webm"],
148
- document: ["application/pdf", "application/msword"]
215
+ document: ["application/pdf", "application/msword"],
149
216
  };
@@ -7,6 +7,8 @@ declare class SequelizeConnector extends BaseConnector<Sequelize> {
7
7
  private constructor();
8
8
  static getInstance(): SequelizeConnector;
9
9
  private formatSQLQueryLog;
10
+ private coerceBoolean;
11
+ private coerceNumber;
10
12
  private createSequelizeInstance;
11
13
  private ensureDatabaseExists;
12
14
  connect(options?: SequelizeConnectionOptions): Promise<Sequelize>;
@@ -35,18 +35,32 @@ class SequelizeConnector extends base_connector_1.default {
35
35
  this.logger.error("Failed to log SQL query", { error });
36
36
  }
37
37
  };
38
+ coerceBoolean(value, fallback) {
39
+ if (typeof value === "boolean")
40
+ return value;
41
+ if (typeof value === "string") {
42
+ return ["true", "1", "yes", "on"].includes(value.trim().toLowerCase());
43
+ }
44
+ if (typeof value === "number")
45
+ return value === 1;
46
+ return fallback;
47
+ }
48
+ coerceNumber(value, fallback) {
49
+ const parsed = Number(value);
50
+ return Number.isFinite(parsed) ? parsed : fallback;
51
+ }
38
52
  // ------------------------------------------------
39
53
  // Create Sequelize instance (shared)
40
54
  // ------------------------------------------------
41
55
  createSequelizeInstance(options = {}) {
42
56
  const dialect = options.dialect ?? this.env_manager.getEnvVar("DB_DIALECT", "postgres");
43
- const logging_enabled = options.logging ?? this.env_manager.getEnvVar("DB_LOGGING", false);
57
+ const logging_enabled = this.coerceBoolean(options.logging ?? this.env_manager.getEnvVar("DB_LOGGING", false), false);
44
58
  const logging = logging_enabled ? this.formatSQLQueryLog : false;
45
59
  const database = options.database ?? this.env_manager.getEnvVar("DB_NAME");
46
60
  const username = options.username ?? this.env_manager.getEnvVar("DB_USER");
47
61
  const password = options.password ?? this.env_manager.getEnvVar("DB_PASSWORD");
48
62
  const host = options.host ?? this.env_manager.getEnvVar("DB_HOST");
49
- const port = options.port ?? this.env_manager.getEnvVar("DB_PORT", 5432);
63
+ const port = this.coerceNumber(options.port ?? this.env_manager.getEnvVar("DB_PORT", 5432), 5432);
50
64
  return new sequelize_1.Sequelize({
51
65
  database,
52
66
  username,
@@ -79,28 +93,36 @@ class SequelizeConnector extends base_connector_1.default {
79
93
  dialect,
80
94
  logging: false,
81
95
  });
82
- await admin.authenticate();
83
- switch (dialect) {
84
- case "postgres": {
85
- const [rows] = await admin.query(`SELECT 1 FROM pg_database WHERE datname = :db`, { replacements: { db: database } });
86
- if (rows.length === 0) {
87
- await admin.query(`CREATE DATABASE "${database}"`);
88
- this.logger.info(`📦 Created DB ${database}`);
96
+ try {
97
+ await admin.authenticate();
98
+ const queryInterface = admin.getQueryInterface();
99
+ const quoted_database = queryInterface.quoteIdentifier(database);
100
+ switch (dialect) {
101
+ case "postgres": {
102
+ const [rows] = await admin.query(`SELECT 1 FROM pg_database WHERE datname = :db`, { replacements: { db: database } });
103
+ if (rows.length === 0) {
104
+ await admin.query(`CREATE DATABASE ${quoted_database}`);
105
+ this.logger.info(`📦 Created DB ${database}`);
106
+ }
107
+ break;
108
+ }
109
+ case "mysql":
110
+ case "mariadb":
111
+ await admin.query(`CREATE DATABASE IF NOT EXISTS ${quoted_database}`);
112
+ break;
113
+ case "mssql": {
114
+ const escaped_database = database.replace(/'/g, "''");
115
+ await admin.query(`
116
+ IF DB_ID('${escaped_database}') IS NULL
117
+ CREATE DATABASE ${quoted_database}
118
+ `);
119
+ break;
89
120
  }
90
- break;
91
121
  }
92
- case "mysql":
93
- case "mariadb":
94
- await admin.query(`CREATE DATABASE IF NOT EXISTS \`${database}\``);
95
- break;
96
- case "mssql":
97
- await admin.query(`
98
- IF DB_ID('${database}') IS NULL
99
- CREATE DATABASE [${database}]
100
- `);
101
- break;
102
122
  }
103
- await admin.close();
123
+ finally {
124
+ await admin.close();
125
+ }
104
126
  }
105
127
  catch (error) {
106
128
  this.logger.error(`DB auto-create skipped: ${database}`, { error });