fiberx-backend-toolkit 0.0.14 → 0.0.16

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 (84) hide show
  1. package/dist/code_templates/sequelize_code_template.d.ts +8 -0
  2. package/dist/code_templates/sequelize_code_template.js +382 -0
  3. package/dist/config/constants.d.ts +20 -0
  4. package/dist/config/constants.js +24 -0
  5. package/dist/database/connectors/base_connector.d.ts +12 -0
  6. package/dist/database/connectors/base_connector.js +14 -0
  7. package/dist/database/connectors/sequelize_connector.d.ts +17 -0
  8. package/dist/database/connectors/sequelize_connector.js +93 -0
  9. package/dist/database/index.d.ts +11 -141
  10. package/dist/database/index.js +15 -1309
  11. package/dist/database/schema/schema_diff_util.d.ts +6 -0
  12. package/dist/database/schema/schema_diff_util.js +68 -0
  13. package/dist/database/schema/schema_normalizer_util.d.ts +23 -0
  14. package/dist/database/schema/schema_normalizer_util.js +39 -0
  15. package/dist/database/scripts/create_schema_script.d.ts +13 -0
  16. package/dist/database/scripts/create_schema_script.js +82 -0
  17. package/dist/database/scripts/create_seeder_script.d.ts +15 -0
  18. package/dist/database/scripts/create_seeder_script.js +86 -0
  19. package/dist/database/scripts/make_migrations_script.d.ts +16 -0
  20. package/dist/database/scripts/make_migrations_script.js +172 -0
  21. package/dist/database/scripts/migration_runner_script.d.ts +15 -0
  22. package/dist/database/scripts/migration_runner_script.js +139 -0
  23. package/dist/database/scripts/seeder_runner_script.d.ts +15 -0
  24. package/dist/database/scripts/seeder_runner_script.js +126 -0
  25. package/dist/database/scripts/sequelize_model_generator_script.d.ts +11 -0
  26. package/dist/database/scripts/sequelize_model_generator_script.js +108 -0
  27. package/dist/index.d.ts +5 -4
  28. package/dist/index.js +5 -1
  29. package/dist/middle_ware/cookie_manager_middle_ware.d.ts +22 -0
  30. package/dist/middle_ware/cookie_manager_middle_ware.js +65 -0
  31. package/dist/middle_ware/cors_middle_ware.d.ts +20 -0
  32. package/dist/middle_ware/cors_middle_ware.js +120 -0
  33. package/dist/middle_ware/https_enforcement_middle_ware.d.ts +12 -0
  34. package/dist/middle_ware/https_enforcement_middle_ware.js +41 -0
  35. package/dist/middle_ware/index.d.ts +8 -107
  36. package/dist/middle_ware/index.js +8 -443
  37. package/dist/middle_ware/rate_limiter_middle_ware.d.ts +16 -0
  38. package/dist/middle_ware/rate_limiter_middle_ware.js +75 -0
  39. package/dist/middle_ware/request_logger_middle_ware.d.ts +8 -0
  40. package/dist/middle_ware/request_logger_middle_ware.js +35 -0
  41. package/dist/middle_ware/response_formatter_middle_ware.d.ts +16 -0
  42. package/dist/middle_ware/response_formatter_middle_ware.js +75 -0
  43. package/dist/middle_ware/secure_headers_middle_ware.d.ts +22 -0
  44. package/dist/middle_ware/secure_headers_middle_ware.js +97 -0
  45. package/dist/types/database_type.d.ts +16 -0
  46. package/dist/types/database_type.js +1 -0
  47. package/dist/types/index.d.ts +5 -4
  48. package/dist/types/index.js +5 -7
  49. package/dist/{middle_ware_type-D8LA7qF3.d.ts → types/middle_ware_type.d.ts} +8 -10
  50. package/dist/types/middle_ware_type.js +2 -0
  51. package/dist/types/migration_type.d.ts +5 -0
  52. package/dist/types/migration_type.js +1 -0
  53. package/dist/{database_type-C8LkcL6x.d.ts → types/schema_type.d.ts} +8 -33
  54. package/dist/types/schema_type.js +2 -0
  55. package/dist/{util_type-Yyo1nXmm.d.ts → types/util_type.d.ts} +7 -9
  56. package/dist/types/util_type.js +7 -0
  57. package/dist/utils/cache_util.d.ts +40 -0
  58. package/dist/utils/cache_util.js +81 -0
  59. package/dist/utils/env_manager_util.d.ts +16 -0
  60. package/dist/utils/env_manager_util.js +85 -0
  61. package/dist/utils/index.d.ts +9 -265
  62. package/dist/utils/index.js +9 -22
  63. package/dist/utils/input_transformer_util.d.ts +115 -0
  64. package/dist/utils/input_transformer_util.js +309 -0
  65. package/dist/utils/input_validator_util.d.ts +53 -0
  66. package/dist/utils/input_validator_util.js +116 -0
  67. package/dist/{env_manager_util-DLs1b9Q7.d.ts → utils/logger_util.d.ts} +2 -19
  68. package/dist/utils/logger_util.js +85 -0
  69. package/dist/utils/safe_execute_util.d.ts +25 -0
  70. package/dist/utils/safe_execute_util.js +141 -0
  71. package/dist/utils/server_util.d.ts +12 -0
  72. package/dist/utils/server_util.js +57 -0
  73. package/dist/utils/sql_formatter_util.d.ts +19 -0
  74. package/dist/utils/sql_formatter_util.js +43 -0
  75. package/package.json +2 -9
  76. package/dist/chunk-6AJLW7HC.js +0 -32
  77. package/dist/chunk-6AJLW7HC.js.map +0 -1
  78. package/dist/chunk-BLYKIQXQ.js +0 -1042
  79. package/dist/chunk-BLYKIQXQ.js.map +0 -1
  80. package/dist/database/index.js.map +0 -1
  81. package/dist/index.js.map +0 -1
  82. package/dist/middle_ware/index.js.map +0 -1
  83. package/dist/types/index.js.map +0 -1
  84. package/dist/utils/index.js.map +0 -1
@@ -0,0 +1,8 @@
1
+ import { SchemaColumnInterface, SchemaDiffInterface } from "../types/schema_type";
2
+ declare const SEQUELIZE_SCHEMA_CODE_TEMPLATE: (schema_name: string, table_name: string, model_name: string, migration_priority: number) => string;
3
+ declare const SEQUELIZE_CREATE_NEW_SCHEMA_MIGRATION_FILE_CODE_TEMPLATE: (schema_table_name: string, schema_model_name: string, schema_file_name: string) => string;
4
+ declare const SEQUELIZE_UPDATE_EXISTING_SCHEMA_MIGRATION_FILE_CODE_TEMPLATE: (schema_table_name: string, schema_model_name: string, diff: SchemaDiffInterface, schema_file_name: string) => string;
5
+ declare const SEQUELIZE_SEEDER_TEMPLATE: (class_name: string, table_name: string) => string;
6
+ declare const SEQUELIZE_MODEL_CODE_TEMPLATE: (schema_model_name: string, schema_file_name: string, schema_columns: Record<string, SchemaColumnInterface>) => string;
7
+ declare const SEQUELIZE_MODELS_INDEX_CODE_TEMPLATE: (model_names: string[], imports: string) => string;
8
+ export { SEQUELIZE_SCHEMA_CODE_TEMPLATE, SEQUELIZE_SEEDER_TEMPLATE, SEQUELIZE_CREATE_NEW_SCHEMA_MIGRATION_FILE_CODE_TEMPLATE, SEQUELIZE_UPDATE_EXISTING_SCHEMA_MIGRATION_FILE_CODE_TEMPLATE, SEQUELIZE_MODEL_CODE_TEMPLATE, SEQUELIZE_MODELS_INDEX_CODE_TEMPLATE };
@@ -0,0 +1,382 @@
1
+ const SEQUELIZE_SCHEMA_CODE_TEMPLATE = (schema_name, table_name, model_name, migration_priority) => {
2
+ return `
3
+ import { DataTypes } from "sequelize";
4
+ import { SchemaDefinitionInterface } from "fiberx-backend-toolkit/types/schema_type";
5
+
6
+ const ${schema_name}: SchemaDefinitionInterface = {
7
+ database_name: "public",
8
+ migration_priority: ${migration_priority},
9
+
10
+ table_name: "${table_name}",
11
+ model_name: "${model_name}",
12
+ timestamps:true,
13
+
14
+ columns: {
15
+ id: {
16
+ type: DataTypes.BIGINT,
17
+ primaryKey: true,
18
+ autoIncrement: true,
19
+ allowNull: false,
20
+ },
21
+
22
+ created_at: {
23
+ type: DataTypes.DATE,
24
+ defaultValue: DataTypes.NOW,
25
+ },
26
+
27
+ updated_at: {
28
+ type: DataTypes.DATE,
29
+ allowNull: true,
30
+ defaultValue: null,
31
+ },
32
+ },
33
+
34
+ indexes: [
35
+ { fields: [""], name: "" },
36
+ ],
37
+ };
38
+
39
+ export default ${schema_name};
40
+ `;
41
+ };
42
+ const SEQUELIZE_CREATE_NEW_SCHEMA_MIGRATION_FILE_CODE_TEMPLATE = (schema_table_name, schema_model_name, schema_file_name) => `
43
+ import { QueryInterface, DataTypes, Sequelize } from "sequelize";
44
+ import { LoggerUtil } from "fiberx-backend-toolkit//utils";
45
+ import { SchemaDefinitionInterface } from "fiberx-backend-toolkit/types/schema_type";
46
+ import ${schema_model_name}Schema from "@/database/schemas/${schema_file_name.replace(".ts", "")}";
47
+
48
+ class Create${schema_model_name}TableMigration {
49
+ private name: string = "create_table_${schema_table_name}_migration_file";
50
+ private schema: SchemaDefinitionInterface = ${schema_model_name}Schema;
51
+ private readonly logger: LoggerUtil = new LoggerUtil(this.name);
52
+
53
+ constructor() {}
54
+
55
+ // Migration UP
56
+ public async up(
57
+ queryInterface: QueryInterface,
58
+ Sequelize: typeof import("sequelize")
59
+ ) {
60
+ try {
61
+ const { table_name, columns = {}, indexes = [] } = this.schema;
62
+
63
+ await queryInterface.createTable(table_name, columns);
64
+
65
+ for (const index_field_obj of indexes) {
66
+
67
+ const { fields, name, index_options } = index_field_obj;
68
+ const index_name = \`idx_\${table_name}_\${fields.join("_")}\`
69
+
70
+ await queryInterface.addIndex(
71
+ table_name,
72
+ fields,
73
+ { name: index_name, ...index_options }
74
+ );
75
+ }
76
+
77
+ this.logger.success(\`✅ Table "\${table_name}" for schema "\${model_name}Schema" created with "\${this.index_attributes.length}" indexed Fields.\`);
78
+ }
79
+ catch (error: any) {
80
+ this.logger.error(\`🚫 Migration failed: "\${error.message}"\`, { error });
81
+ throw new Error(\`🚫 Migration failed: "\${error.message}"\`);
82
+ }
83
+ }
84
+
85
+ // Migration DOWN
86
+ public async down(
87
+ queryInterface: QueryInterface,
88
+ Sequelize: typeof import("sequelize")
89
+ ) {
90
+ try {
91
+ const { table_name, database_name, model_name } = this.schema;
92
+ await queryInterface.dropTable(table_name, {});
93
+ this.logger.success(\`🗑️ Table "\${table_name}" dropped successfully.\`);
94
+ } catch (error: any) {
95
+ this.logger.error(\`🚫 Migration rollback failed: "\${error.message}"\`, { error });
96
+ throw new Error(\`🚫 Migration rollback failed: "\${error.message}"\`);
97
+ }
98
+ }
99
+ }
100
+
101
+ export default Create${schema_model_name}TableMigration;
102
+ `;
103
+ const SEQUELIZE_UPDATE_EXISTING_SCHEMA_MIGRATION_FILE_CODE_TEMPLATE = (schema_table_name, schema_model_name, diff, schema_file_name) => `
104
+ import { QueryInterface, DataTypes, Sequelize } from "sequelize";
105
+ import { LoggerUtil } from "fiberx-backend-toolkit//utils";
106
+ import { SchemaDefinitionInterface } from "fiberx-backend-toolkit/types/schema_type";
107
+ import ${schema_model_name}Schema from "@/database/schemas/${schema_file_name.replace(".ts", "")}";
108
+
109
+ class Update${schema_model_name}TableMigration {
110
+ private name: string = "update_table_${schema_table_name}_migration_file";
111
+ private schema: SchemaDefinitionInterface = ${schema_model_name}Schema;
112
+ private readonly logger: LoggerUtil = new LoggerUtil(this.name);
113
+
114
+ constructor() {}
115
+
116
+ public async up(
117
+ queryInterface: QueryInterface,
118
+ Sequelize: typeof import("sequelize")
119
+ ) {
120
+ try {
121
+ const { table_name, model_name, columns = {}, indexes = [] } = this.schema;
122
+
123
+ ${diff.table_renamed ? `
124
+ await queryInterface.renameTable(
125
+ "${diff.table_renamed.from}",
126
+ "${diff.table_renamed.to}"
127
+ );`
128
+ :
129
+ ""}
130
+
131
+ // Add columns
132
+ ${diff.columns.added.map((column_name) => `
133
+ await queryInterface.addColumn(
134
+ table_name,
135
+ "${column_name}",
136
+ columns["${column_name}"]
137
+ );
138
+ `).join("")}
139
+
140
+ // Modify columns
141
+ ${Object.entries(diff.columns.modified).map(([col_name, col_modified]) => `
142
+ await queryInterface.changeColumn(
143
+ table_name,
144
+ "${col_name}",
145
+ ${JSON.stringify(col_modified?.after)}
146
+ );
147
+ `).join("")}
148
+
149
+ // Remove columns
150
+ ${Object.entries(diff.columns.modified).map(([col_name, col_Def]) => `
151
+ await queryInterface.removeColumn(
152
+ table_name,
153
+ "${col_name}"
154
+ );
155
+ `).join("")}
156
+
157
+
158
+ // Add indexes
159
+ ${diff.indexes.added.map((idx) => `
160
+ await queryInterface.addIndex(
161
+ table_name,
162
+ ${JSON.stringify(idx.fields)},
163
+ ${JSON.stringify(idx)}
164
+ );
165
+ `).join("")}
166
+
167
+ // Modify indexes (remove + add)
168
+ ${Object.entries(diff.indexes.modified).map(([idx_name, idx_modified]) => `
169
+ await queryInterface.removeIndex(
170
+ table_name,
171
+ ${JSON.stringify(idx_modified.before.name)}
172
+ );
173
+
174
+ await queryInterface.addIndex(
175
+ table_name,
176
+ ${JSON.stringify(idx_modified.after.fields)},
177
+ ${JSON.stringify(idx_modified.after)}
178
+ );
179
+ `).join("")}
180
+
181
+ // Remove indexes
182
+ ${diff.indexes.removed.map((idx) => `
183
+ await queryInterface.removeIndex(
184
+ table_name,
185
+ ${JSON.stringify(idx.name)}
186
+ );
187
+ `).join("")}
188
+
189
+
190
+ this.logger.success(\`✅ Table "\${table_name}" for schema "\${model_name}Schema" updated successfully.\`);
191
+ }
192
+ catch (error: any) {
193
+ this.logger.error(\`🚫 Update migration failed: "\${error.message}"\`, { error });
194
+ throw new Error(\`🚫 Update migration failed: "\${error.message}"\`);
195
+ }
196
+ }
197
+
198
+ public async down(
199
+ queryInterface: QueryInterface,
200
+ Sequelize: typeof import("sequelize")
201
+ ) {
202
+ try {
203
+ const { table_name, model_name, columns = {} } = this.schema;
204
+
205
+ // Revert Added indexes
206
+ ${diff.indexes.added.map((idx) => `
207
+ await queryInterface.removeIndex(
208
+ table_name,
209
+ ${JSON.stringify(idx.name)}
210
+ );`).join("")}
211
+
212
+ // Revert Modified Indexes
213
+ ${Object.entries(diff.indexes.modified).map(([idx_name, idx_modified]) => `
214
+ await queryInterface.removeIndex(
215
+ table_name,
216
+ ${JSON.stringify(idx_modified.after.name)}
217
+ );
218
+
219
+
220
+ await queryInterface.addIndex(
221
+ table_name,
222
+ ${JSON.stringify(idx_modified.before.fields)},
223
+ ${JSON.stringify(idx_modified.before)}
224
+ );`).join("")}
225
+
226
+ // Revert removed indexes
227
+ ${diff.indexes.removed.map((idx) => `
228
+ await queryInterface.addIndex(
229
+ table_name,
230
+ ${JSON.stringify(idx.fields)},
231
+ ${JSON.stringify(idx)}
232
+ );`).join("")}
233
+
234
+ // Revert Modified columns
235
+ ${Object.entries(diff.columns.modified).map(([col_name, col_modified]) => `
236
+ await queryInterface.changeColumn(
237
+ table_name,
238
+ "${col_name}",
239
+ ${JSON.stringify(col_modified.before)}
240
+ );`).join("")}
241
+
242
+ // Revert added columns
243
+ ${diff.columns.added.map((column_name) => `
244
+ await queryInterface.removeColumn(table_name, "${column_name}");
245
+ `).join("")}
246
+
247
+ ${Object.entries(diff.columns.modified).map(([col_name, col_Def]) => `
248
+ await queryInterface.addColumn(
249
+ table_name,
250
+ "${col_name}",
251
+ ${JSON.stringify(col_Def)}
252
+ );
253
+ `).join("")}
254
+
255
+ ${diff.table_renamed ? `
256
+ await queryInterface.renameTable(
257
+ "${diff.table_renamed.to}",
258
+ "${diff.table_renamed.from}"
259
+ );` : ""}
260
+
261
+ this.logger.success(\`🗑️ Rollback of table "\${table_name}" completed successfully.\`);
262
+ }
263
+ catch (error: any) {
264
+ this.logger.error(\`🚫 Rollback migration failed: "\${error.message}"\`, { error });
265
+ throw new Error(\`🚫 Rollback migration failed: "\${error.message}"\`);
266
+ }
267
+ }
268
+ }
269
+
270
+ export default Update${schema_model_name}TableMigration;
271
+ `;
272
+ const SEQUELIZE_SEEDER_TEMPLATE = (class_name, table_name) => `
273
+ 'use strict';
274
+
275
+ import { QueryInterface } from 'sequelize';
276
+
277
+ class ${class_name}Seeder {
278
+ /**
279
+ * Seed method
280
+ */
281
+ public async up(queryInterface: QueryInterface): Promise<void> {
282
+ const seed_data = this.getSeedData();
283
+
284
+ if (!seed_data || seed_data.length === 0) {
285
+ throw new Error("❌ Seeder data for 'roles' is empty. Aborting bulk insert.");
286
+ }
287
+
288
+ await queryInterface.bulkInsert('${table_name.toLowerCase()}', seed_data);
289
+ }
290
+
291
+ /**
292
+ * Undo seed method
293
+ */
294
+ public async down(queryInterface: QueryInterface): Promise<void> {
295
+ const seed_data = this.getSeedData();
296
+
297
+ if (!seed_data || seed_data.length === 0) {
298
+ throw new Error("❌ Seeder data for 'roles' is empty. Nothing to delete.");
299
+ }
300
+
301
+ const ids = seed_data.map(row => row.id);
302
+
303
+ await queryInterface.bulkDelete('${table_name.toLowerCase()}', { id: ids });
304
+ }
305
+
306
+ /**
307
+ * Provide seed data array
308
+ */
309
+ private getSeedData(): Array<Record<string, any>> {
310
+ // TODO: Replace this with real seed data
311
+ return [];
312
+ }
313
+ }
314
+
315
+ export default ${class_name}Seeder;
316
+ `;
317
+ const SEQUELIZE_MODEL_CODE_TEMPLATE = (schema_model_name, schema_file_name, schema_columns) => {
318
+ const attributes = Object.keys(schema_columns)
319
+ .map(col => ` declare ${col}: any;`)
320
+ .join("\n");
321
+ return `
322
+ import { Model, Sequelize } from "sequelize";
323
+ import ${schema_model_name}Schema from "@/database/schemas/${schema_file_name.replace(".ts", "")}";
324
+
325
+
326
+ class ${schema_model_name} extends Model {
327
+ ${attributes}
328
+
329
+ public static initModel(sequelize: Sequelize): typeof ${schema_model_name} {
330
+ sequelize: Sequelize
331
+ ): ${schema_model_name} {
332
+ ${schema_model_name}.init(
333
+ ${schema_model_name}Schema.columns,
334
+ {
335
+ sequelize,
336
+ tableName: ${schema_model_name}Schema.table_name,
337
+ modelName: ${schema_model_name}Schema.model_name,
338
+ timestamps: ${schema_model_name}Schema.timestamps,
339
+ indexes: ${schema_model_name}Schema.indexes,
340
+ createdAt: "created_at",
341
+ updatedAt: "updated_at",
342
+ hooks: {}
343
+ }
344
+ );
345
+ return ${schema_model_name};
346
+ }
347
+
348
+ public static registerAssociations(): void {
349
+ // Example:
350
+ // User.belongsTo(models.Organization, { foreignKey: "org_id" });
351
+ }
352
+ }
353
+
354
+ export default ${schema_model_name}
355
+ `;
356
+ };
357
+ const SEQUELIZE_MODELS_INDEX_CODE_TEMPLATE = (model_names, imports) => {
358
+ const exports = model_names.join(",\n ");
359
+ return `
360
+ import { Sequelize } from "sequelize";
361
+ ${imports}
362
+
363
+ const models = {
364
+ ${exports}
365
+ };
366
+
367
+ export const initModels = (sequelize: Sequelize) => {
368
+ Object.values(models).forEach(model => {
369
+ model.initModel(sequelize);
370
+ });
371
+
372
+ Object.values(models).forEach(model => {
373
+ model.registerAssociations();
374
+ });
375
+
376
+ return models;
377
+ };
378
+
379
+ export default models;
380
+ `;
381
+ };
382
+ export { SEQUELIZE_SCHEMA_CODE_TEMPLATE, SEQUELIZE_SEEDER_TEMPLATE, SEQUELIZE_CREATE_NEW_SCHEMA_MIGRATION_FILE_CODE_TEMPLATE, SEQUELIZE_UPDATE_EXISTING_SCHEMA_MIGRATION_FILE_CODE_TEMPLATE, SEQUELIZE_MODEL_CODE_TEMPLATE, SEQUELIZE_MODELS_INDEX_CODE_TEMPLATE };
@@ -0,0 +1,20 @@
1
+ export declare const BASE_DIR: string;
2
+ export declare const LOG_DIR: string;
3
+ export declare const ENV_VAR_DIR: string;
4
+ export declare const SCHEMAS_DIR: string;
5
+ export declare const SCHEMA_SNAPSHOTS_DIR: string;
6
+ export declare const MODELS_DIR: string;
7
+ export declare const MIGRATIONS_DIR: string;
8
+ export declare const SEEDERS_DIR: string;
9
+ export declare const SEQUELIZE_META_TABLE_NAME = "sequelize_database_tables_meta";
10
+ export declare const SEQUELIZE_SEEDER_META_TABLE_NAME = "sequelize_database_table_seeder_meta";
11
+ export declare const REQUEST_ID_COOKIE_MAX_AGE: number;
12
+ export declare const CORS_ALLOWED_METHODS: string[];
13
+ export declare const CORS_ALLOWED_HEADERS: string[];
14
+ export declare const CORS_MAX_AGE_IN_SECONDS = 600;
15
+ export declare const CORS_MAX_AGE_IN_MICRO_SECONDS: number;
16
+ export declare const REQUEST_RATE_LIMITTER_OPTIONS: {
17
+ window_ms: number;
18
+ max_requests: number;
19
+ message: string;
20
+ };
@@ -0,0 +1,24 @@
1
+ import path from "path";
2
+ // Database constants
3
+ export const BASE_DIR = process.cwd();
4
+ export const LOG_DIR = path.join(BASE_DIR, "logs");
5
+ export const ENV_VAR_DIR = path.join(BASE_DIR, "environment_varaiables");
6
+ export const SCHEMAS_DIR = path.join(BASE_DIR, "src/database/schemas");
7
+ export const SCHEMA_SNAPSHOTS_DIR = path.join(BASE_DIR, "src/database/schema_snapshots");
8
+ export const MODELS_DIR = path.join(BASE_DIR, "src/database/models");
9
+ export const MIGRATIONS_DIR = path.join(BASE_DIR, "src/database/migrations");
10
+ export const SEEDERS_DIR = path.join(BASE_DIR, "src/database/seeders");
11
+ export const SEQUELIZE_META_TABLE_NAME = "sequelize_database_tables_meta";
12
+ export const SEQUELIZE_SEEDER_META_TABLE_NAME = "sequelize_database_table_seeder_meta";
13
+ export const REQUEST_ID_COOKIE_MAX_AGE = (1000 * 60 * 60 * 24 * 7); // 7 days
14
+ // CORS constants
15
+ export const CORS_ALLOWED_METHODS = ["GET", "POST", "PATCH", "DELETE", "OPTIONS"];
16
+ export const CORS_ALLOWED_HEADERS = ["Content-Type", "Authorization", "X-Device-Id", "X-Device-Name", "User-Agent"];
17
+ export const CORS_MAX_AGE_IN_SECONDS = (600); // default: 10 min
18
+ export const CORS_MAX_AGE_IN_MICRO_SECONDS = (1000 * 60 * 10); // 10 minutes
19
+ // Rate limitter
20
+ export const REQUEST_RATE_LIMITTER_OPTIONS = {
21
+ window_ms: (60 * 1000), // 1 MINS
22
+ max_requests: 50,
23
+ message: "⏳ Too many requests from this IP, please try again later"
24
+ };
@@ -0,0 +1,12 @@
1
+ import { LoggerUtil, EnvManagerUtil } from "../../utils";
2
+ /**
3
+ * Base connector abstraction for all DB / external service connectors
4
+ */
5
+ declare abstract class BaseConnector<TConnection> {
6
+ protected readonly connector_name: string;
7
+ readonly env_manager: EnvManagerUtil;
8
+ readonly logger: LoggerUtil;
9
+ protected constructor(connector_name: string);
10
+ abstract connect(): TConnection;
11
+ }
12
+ export default BaseConnector;
@@ -0,0 +1,14 @@
1
+ import { LoggerUtil, EnvManagerUtil } from "../../utils";
2
+ /**
3
+ * Base connector abstraction for all DB / external service connectors
4
+ */
5
+ class BaseConnector {
6
+ connector_name;
7
+ env_manager = EnvManagerUtil.getInstance();
8
+ logger;
9
+ constructor(connector_name) {
10
+ this.connector_name = connector_name;
11
+ this.logger = new LoggerUtil(connector_name);
12
+ }
13
+ }
14
+ export default BaseConnector;
@@ -0,0 +1,17 @@
1
+ import { Sequelize } from "sequelize";
2
+ import BaseConnector from "./base_connector";
3
+ import { SequelizeConnectionOptions } from "../../types/database_type";
4
+ declare class SequelizeConnector extends BaseConnector<Sequelize> {
5
+ private static instance;
6
+ private static connections;
7
+ private constructor();
8
+ static getInstance(): SequelizeConnector;
9
+ private formatSQLQueryLog;
10
+ connect(options?: SequelizeConnectionOptions): Sequelize;
11
+ connectNamed(name: string, options?: SequelizeConnectionOptions): Sequelize;
12
+ getConnection(name?: string): Sequelize | undefined;
13
+ hasConnection(name?: string): boolean;
14
+ closeConnection(name?: string): Promise<void>;
15
+ closeAll(): Promise<void>;
16
+ }
17
+ export default SequelizeConnector;
@@ -0,0 +1,93 @@
1
+ import { Sequelize } from "sequelize";
2
+ import BaseConnector from "./base_connector";
3
+ import SqlFormatterUtil from "../../utils/sql_formatter_util";
4
+ class SequelizeConnector extends BaseConnector {
5
+ static instance;
6
+ static connections = new Map();
7
+ constructor() {
8
+ super("sequelize_connector");
9
+ }
10
+ static getInstance() {
11
+ if (!SequelizeConnector.instance) {
12
+ SequelizeConnector.instance = new SequelizeConnector();
13
+ }
14
+ return SequelizeConnector.instance;
15
+ }
16
+ // ----------------------------------
17
+ // SQL logging
18
+ // ----------------------------------
19
+ formatSQLQueryLog = (sql, timing) => {
20
+ try {
21
+ const formatted = SqlFormatterUtil.format(sql);
22
+ if (typeof timing === "number") {
23
+ this.logger.info(`[SQL ${timing}ms] ${formatted}`);
24
+ }
25
+ else {
26
+ this.logger.info(`[SQL] ${formatted}`);
27
+ }
28
+ }
29
+ catch (error) {
30
+ this.logger.error("Failed to log SQL query", { error });
31
+ }
32
+ };
33
+ // ----------------------------------
34
+ // Single default connection
35
+ // ----------------------------------
36
+ connect(options = {}) {
37
+ return this.connectNamed(options.name ?? "default", options);
38
+ }
39
+ // ----------------------------------
40
+ // Multiple named connections
41
+ // ----------------------------------
42
+ connectNamed(name, options = {}) {
43
+ if (SequelizeConnector.connections.has(name)) {
44
+ return SequelizeConnector.connections.get(name);
45
+ }
46
+ const dialect = options.dialect ?? this.env_manager.getEnvVar("DB_DIALECT", "postgres");
47
+ const logging_enabled = options.logging ?? this.env_manager.getEnvVar("DB_LOGGING", false);
48
+ const logging = logging_enabled ? this.formatSQLQueryLog : false;
49
+ const database = options.database ?? this.env_manager.getEnvVar("DB_NAME");
50
+ const username = options.username ?? this.env_manager.getEnvVar("DB_USER");
51
+ const password = options.password ?? this.env_manager.getEnvVar("DB_PASSWORD");
52
+ const host = options.host ?? this.env_manager.getEnvVar("DB_HOST");
53
+ const port = options.port ?? this.env_manager.getEnvVar("DB_PORT", 5432);
54
+ const sequelize = new Sequelize({
55
+ database,
56
+ username,
57
+ password,
58
+ host,
59
+ port,
60
+ dialect,
61
+ logging,
62
+ benchmark: logging_enabled,
63
+ });
64
+ SequelizeConnector.connections.set(name, sequelize);
65
+ this.logger.success(`✅ Sequelize connected [${name}]`);
66
+ return sequelize;
67
+ }
68
+ // ----------------------------------
69
+ // Utilities
70
+ // ----------------------------------
71
+ getConnection(name = "default") {
72
+ return SequelizeConnector.connections.get(name);
73
+ }
74
+ hasConnection(name = "default") {
75
+ return SequelizeConnector.connections.has(name);
76
+ }
77
+ async closeConnection(name = "default") {
78
+ const conn = SequelizeConnector.connections.get(name);
79
+ if (conn) {
80
+ await conn.close();
81
+ SequelizeConnector.connections.delete(name);
82
+ this.logger.info(`🔌 Sequelize connection closed [${name}]`);
83
+ }
84
+ }
85
+ async closeAll() {
86
+ for (const [name, conn] of SequelizeConnector.connections.entries()) {
87
+ await conn.close();
88
+ this.logger.info(`🔌 Sequelize connection closed [${name}]`);
89
+ }
90
+ SequelizeConnector.connections.clear();
91
+ }
92
+ }
93
+ export default SequelizeConnector;