fiberx-backend-toolkit 0.0.1 → 0.0.7
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.
- package/dist/chunk-BK6YPN2O.js +1029 -0
- package/dist/chunk-BK6YPN2O.js.map +1 -0
- package/dist/chunk-FKITWVZO.js +21 -0
- package/dist/chunk-FKITWVZO.js.map +1 -0
- package/dist/database/index.d.ts +126 -0
- package/dist/database/index.js +1105 -0
- package/dist/database/index.js.map +1 -0
- package/dist/env_manager_util-DLs1b9Q7.d.ts +45 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +94 -0
- package/dist/types/index.js +7 -0
- package/dist/types/index.js.map +1 -0
- package/dist/util_type-Yyo1nXmm.d.ts +39 -0
- package/dist/utils/index.d.ts +264 -0
- package/dist/utils/index.js +22 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +8 -2
- package/src/code_templates/sequelize_code_template.ts +0 -362
- package/src/config/constants.ts +0 -14
- package/src/database/connectors/base_connector.ts +0 -21
- package/src/database/connectors/sequelize_connector.ts +0 -66
- package/src/database/index.ts +0 -27
- package/src/database/schema/schema_diff_util.ts +0 -96
- package/src/database/schema/schema_normalizer_util.ts +0 -54
- package/src/database/scripts/create_schema_script.ts +0 -108
- package/src/database/scripts/create_seeder_script.ts +0 -118
- package/src/database/scripts/make_migrations_script.ts +0 -275
- package/src/database/scripts/migration_runner_script.ts +0 -184
- package/src/database/scripts/seeder_runner_script.ts +0 -167
- package/src/index.ts +0 -2
- package/src/types/index.ts +0 -3
- package/src/types/migration_type.ts +0 -7
- package/src/types/schema_type.ts +0 -101
- package/src/types/util_type.ts +0 -36
- package/src/utils/env_manager_util.ts +0 -90
- package/src/utils/index.ts +0 -15
- package/src/utils/input_transformer_util.ts +0 -433
- package/src/utils/input_validator_util.ts +0 -156
- package/src/utils/logger_util.ts +0 -119
- package/src/utils/server_util.ts +0 -71
- package/src/utils/sql_formatter_util.ts +0 -50
- package/test.js +0 -1
- package/tsconfig.json +0 -25
- package/tsup.config.ts +0 -14
|
@@ -0,0 +1,1029 @@
|
|
|
1
|
+
// src/utils/logger_util.ts
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path2 from "path";
|
|
4
|
+
|
|
5
|
+
// src/config/constants.ts
|
|
6
|
+
import path from "path";
|
|
7
|
+
var BASE_DIR = process.cwd();
|
|
8
|
+
var LOG_DIR = path.join(BASE_DIR, "logs");
|
|
9
|
+
var ENV_VAR_DIR = path.join(BASE_DIR, "environment_varaiables");
|
|
10
|
+
var SCHEMAS_DIR = path.join(BASE_DIR, "src/database/schemas");
|
|
11
|
+
var SCHEMA_SNAPSHOTS_DIR = path.join(BASE_DIR, "src/database/schema_snapshots");
|
|
12
|
+
var MODELS_DIR = path.join(BASE_DIR, "src/database/models");
|
|
13
|
+
var MIGRATIONS_DIR = path.join(BASE_DIR, "src/database/migrations");
|
|
14
|
+
var SEEDERS_DIR = path.join(BASE_DIR, "src/database/seeders");
|
|
15
|
+
var SEQUELIZE_META_TABLE_NAME = "sequelize_database_tables_meta";
|
|
16
|
+
var SEQUELIZE_SEEDER_META_TABLE_NAME = "sequelize_database_table_seeder_meta";
|
|
17
|
+
var REQUEST_ID_COOKIE_MAX_AGE = 1e3 * 60 * 60 * 24 * 7;
|
|
18
|
+
var CORS_MAX_AGE_IN_MICRO_SECONDS = 1e3 * 60 * 10;
|
|
19
|
+
var REQUEST_RATE_LIMITTER_OPTIONS = {
|
|
20
|
+
window_ms: 60 * 1e3,
|
|
21
|
+
// 1 MINS
|
|
22
|
+
max_requests: 50,
|
|
23
|
+
message: "\u23F3 Too many requests from this IP, please try again later"
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// src/utils/logger_util.ts
|
|
27
|
+
var LoggerUtil = class {
|
|
28
|
+
module_name;
|
|
29
|
+
base_dir;
|
|
30
|
+
log_file_path;
|
|
31
|
+
log_directory;
|
|
32
|
+
store_log_locally;
|
|
33
|
+
constructor(module_name) {
|
|
34
|
+
this.module_name = module_name;
|
|
35
|
+
this.store_log_locally = true;
|
|
36
|
+
this.base_dir = process.cwd();
|
|
37
|
+
this.log_directory = this.ensureDirExists(LOG_DIR);
|
|
38
|
+
this.log_file_path = this.getLogFilePath();
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Ensures a directory exists. If it doesn't, creates it.
|
|
42
|
+
* @param directory_path - Path to the directory
|
|
43
|
+
* @returns The absolute path of the ensured directory
|
|
44
|
+
*/
|
|
45
|
+
ensureDirExists(directory_path) {
|
|
46
|
+
const resolved_path = path2.resolve(directory_path);
|
|
47
|
+
if (!fs.existsSync(resolved_path)) {
|
|
48
|
+
fs.mkdirSync(resolved_path, { recursive: true });
|
|
49
|
+
}
|
|
50
|
+
return resolved_path;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Generate log unique log file name with timestamp and module name
|
|
54
|
+
* @returns The absolute path of the module log file
|
|
55
|
+
*/
|
|
56
|
+
getLogFilePath() {
|
|
57
|
+
const timestamp = Math.floor(Date.now() / 1e3);
|
|
58
|
+
const file_name = `${this.module_name}-${timestamp}.log`;
|
|
59
|
+
const log_file_path = path2.join(this.log_directory, file_name);
|
|
60
|
+
return log_file_path;
|
|
61
|
+
}
|
|
62
|
+
// Safely stringify objects while avoiding circular references
|
|
63
|
+
safeStringify(obj, space = 2) {
|
|
64
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
65
|
+
return JSON.stringify(
|
|
66
|
+
obj,
|
|
67
|
+
(key, value) => {
|
|
68
|
+
if (typeof value === "object" && value !== null) {
|
|
69
|
+
if (seen.has(value)) {
|
|
70
|
+
return "[Circular]";
|
|
71
|
+
}
|
|
72
|
+
seen.add(value);
|
|
73
|
+
}
|
|
74
|
+
return value;
|
|
75
|
+
},
|
|
76
|
+
space
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
// Log a message with optional error data and level
|
|
80
|
+
log(message = "", data_error = {}, status = "INFO") {
|
|
81
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
82
|
+
const error_str = data_error && typeof data_error === "object" && Object.keys(data_error).length ? this.safeStringify(data_error, 0) : "";
|
|
83
|
+
const formatted_message = message.startsWith(`[${this.module_name}]`) ? message : `[${this.module_name}] ${message}`;
|
|
84
|
+
const log_line = `${timestamp} [${status}] ${formatted_message} ${error_str}
|
|
85
|
+
`;
|
|
86
|
+
const log_entry = { timestamp, status, message, data_error };
|
|
87
|
+
if (this.store_log_locally) {
|
|
88
|
+
fs.appendFileSync(this.log_file_path, log_line);
|
|
89
|
+
}
|
|
90
|
+
console.log(`
|
|
91
|
+
${timestamp} [${status}] ${formatted_message}
|
|
92
|
+
`);
|
|
93
|
+
if (data_error && typeof data_error === "object" && Object.keys(data_error).length) {
|
|
94
|
+
console.log({ ...data_error });
|
|
95
|
+
console.log("\n");
|
|
96
|
+
console.log("========================================");
|
|
97
|
+
}
|
|
98
|
+
return log_entry;
|
|
99
|
+
}
|
|
100
|
+
// Log info-level messages
|
|
101
|
+
info(message, data = "") {
|
|
102
|
+
return this.log(message, data, "INFO");
|
|
103
|
+
}
|
|
104
|
+
// Log error-level messages
|
|
105
|
+
error(message, error = "") {
|
|
106
|
+
return this.log(message, error, "ERROR");
|
|
107
|
+
}
|
|
108
|
+
// Log alert-level messages
|
|
109
|
+
alert(message, data = "") {
|
|
110
|
+
return this.log(message, data, "ALERT");
|
|
111
|
+
}
|
|
112
|
+
// Log success-level messages
|
|
113
|
+
success(message, data = "") {
|
|
114
|
+
return this.log(message, data, "SUCCESS");
|
|
115
|
+
}
|
|
116
|
+
// Log how long a method took to execute
|
|
117
|
+
logExecutionTime(start_time, class_name, method_name) {
|
|
118
|
+
const [seconds, nanoseconds] = process.hrtime(start_time);
|
|
119
|
+
const duration_ms = (seconds * 1e3 + nanoseconds / 1e6).toFixed(2);
|
|
120
|
+
this.info(`${class_name} - ${method_name} completed in ${duration_ms}ms`);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
var logger_util_default = LoggerUtil;
|
|
124
|
+
|
|
125
|
+
// src/utils/input_transformer_util.ts
|
|
126
|
+
import axios from "axios";
|
|
127
|
+
import bcrypt from "bcrypt";
|
|
128
|
+
import dayjs from "dayjs";
|
|
129
|
+
var InputTransformerUtil = class {
|
|
130
|
+
/**
|
|
131
|
+
* Lookup table for number formatting suffixes
|
|
132
|
+
*/
|
|
133
|
+
static count_lookup = [
|
|
134
|
+
{ value: 1, symbol: "" },
|
|
135
|
+
{ value: 1e3, symbol: "K" },
|
|
136
|
+
{ value: 1e6, symbol: "M" },
|
|
137
|
+
{ value: 1e9, symbol: "B" },
|
|
138
|
+
{ value: 1e12, symbol: "T" }
|
|
139
|
+
];
|
|
140
|
+
/**
|
|
141
|
+
* Capitalize the first letter of a string
|
|
142
|
+
*/
|
|
143
|
+
static capitalize(input) {
|
|
144
|
+
return input ? input.charAt(0).toUpperCase() + input.slice(1).toLowerCase() : input;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Capitalize the first letter of each word in a string
|
|
148
|
+
*/
|
|
149
|
+
static capitalizeEachWord(input) {
|
|
150
|
+
if (!input) {
|
|
151
|
+
return "";
|
|
152
|
+
}
|
|
153
|
+
return input.split(" ").map((word) => this.capitalize(word)).join(" ");
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Format date of birth to YYYY-MM-DD
|
|
157
|
+
*/
|
|
158
|
+
static formatDob(dob) {
|
|
159
|
+
return dob ? dayjs(dob).format("YYYY-MM-DD") : null;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Format full name from first and last name
|
|
163
|
+
*/
|
|
164
|
+
static formatMemberFullName(first_name, last_name) {
|
|
165
|
+
return first_name && last_name ? `${first_name} ${last_name}` : null;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Format member preview string
|
|
169
|
+
*/
|
|
170
|
+
static formatMemberPreview(first_name, last_name, public_id) {
|
|
171
|
+
return first_name && last_name && public_id ? `(${public_id}) - ${first_name} ${last_name}` : null;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Format a number with commas
|
|
175
|
+
*/
|
|
176
|
+
static formatAmount(amount) {
|
|
177
|
+
if (!amount) {
|
|
178
|
+
return "0";
|
|
179
|
+
}
|
|
180
|
+
return amount > 0 ? Intl.NumberFormat("en-US").format(amount) : amount.toString();
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Format large numbers with suffixes (K, M, B, T)
|
|
184
|
+
*/
|
|
185
|
+
static nFormatter(num, digits = 1) {
|
|
186
|
+
const lookup_item = this.count_lookup.slice().reverse().find((item) => num >= item.value);
|
|
187
|
+
if (!lookup_item) {
|
|
188
|
+
return "0";
|
|
189
|
+
}
|
|
190
|
+
const formatted_value = (num / lookup_item.value).toFixed(digits).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, "$1");
|
|
191
|
+
return `${formatted_value}${lookup_item.symbol}`;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Round a number to two decimal places
|
|
195
|
+
*/
|
|
196
|
+
static roundToTwoDecimalPlaces(value) {
|
|
197
|
+
if (typeof value !== "number") {
|
|
198
|
+
throw new Error("Input must be a number");
|
|
199
|
+
}
|
|
200
|
+
return Math.round(value * 100) / 100;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Remove leading zeros from a number or string
|
|
204
|
+
*/
|
|
205
|
+
static removeLeadingZeros(value) {
|
|
206
|
+
return value.toString().replace(/^0+/, "") || "0";
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Get country/location based on IP address
|
|
210
|
+
*/
|
|
211
|
+
static async ipAddressToLocation(ip_address = null) {
|
|
212
|
+
try {
|
|
213
|
+
const suffix = !ip_address || ip_address === "::1" ? "s" : `?ip=${ip_address}`;
|
|
214
|
+
const response = await axios.get(`https://ip2c.org/${suffix}`);
|
|
215
|
+
const response_text = response.data.toString();
|
|
216
|
+
if (response_text[0] === "1") {
|
|
217
|
+
const location_parts = response_text.split(";");
|
|
218
|
+
return location_parts[location_parts.length - 1];
|
|
219
|
+
}
|
|
220
|
+
return "Unknown";
|
|
221
|
+
} catch (error) {
|
|
222
|
+
console.error(
|
|
223
|
+
`Error fetching location for IP ${ip_address}:`,
|
|
224
|
+
error
|
|
225
|
+
);
|
|
226
|
+
return "Unknown";
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Convert date of birth string to age
|
|
231
|
+
*/
|
|
232
|
+
static dobToAge(dob_string) {
|
|
233
|
+
const dob_date = new Date(dob_string);
|
|
234
|
+
const today = /* @__PURE__ */ new Date();
|
|
235
|
+
let age = today.getFullYear() - dob_date.getFullYear();
|
|
236
|
+
const month_difference = today.getMonth() - dob_date.getMonth();
|
|
237
|
+
if (month_difference < 0 || month_difference === 0 && today.getDate() < dob_date.getDate()) {
|
|
238
|
+
age--;
|
|
239
|
+
}
|
|
240
|
+
return age;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Hash plain text password
|
|
244
|
+
*/
|
|
245
|
+
static textToPasswordHash(password) {
|
|
246
|
+
return bcrypt.hashSync(password, bcrypt.genSaltSync(10));
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Ensures singular, snake_case, and appends `_schema`
|
|
250
|
+
* Example:
|
|
251
|
+
* - "Users" → "user_schema"
|
|
252
|
+
* - "UserProfile" → "user_profile_schema"
|
|
253
|
+
*/
|
|
254
|
+
static toSchemaFileName(input) {
|
|
255
|
+
const snake = this.toSnakeCase(input);
|
|
256
|
+
const singular = snake.endsWith("s") ? snake.slice(0, -1) : snake;
|
|
257
|
+
return `${singular}_schema`;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Convert snake_case to Title Case
|
|
261
|
+
*/
|
|
262
|
+
static toTitleCase(input) {
|
|
263
|
+
return input.split("_").map(
|
|
264
|
+
(word) => word.charAt(0).toUpperCase() + word.slice(1)
|
|
265
|
+
).join(" ");
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Convert snake_case to PascalCase
|
|
269
|
+
*/
|
|
270
|
+
static toPascalCase(input) {
|
|
271
|
+
return input.split("_").map(
|
|
272
|
+
(word) => word.charAt(0).toUpperCase() + word.slice(1)
|
|
273
|
+
).join("");
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Convert string to snake_case
|
|
277
|
+
*/
|
|
278
|
+
static toSnakeCase(input) {
|
|
279
|
+
return input.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z])([A-Z][a-z])/g, "$1_$2").toLowerCase();
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Pluralize a snake_case string
|
|
283
|
+
*/
|
|
284
|
+
static pluralizeSnakeCase(snake_str) {
|
|
285
|
+
const parts = snake_str.split("_");
|
|
286
|
+
const last_word = parts.pop();
|
|
287
|
+
let plural_word;
|
|
288
|
+
if (last_word.endsWith("y") && !/[aeiou]y$/.test(last_word)) {
|
|
289
|
+
plural_word = last_word.slice(0, -1) + "ies";
|
|
290
|
+
} else if (["s", "x", "z"].includes(last_word.slice(-1)) || last_word.endsWith("ch") || last_word.endsWith("sh")) {
|
|
291
|
+
plural_word = `${last_word}es`;
|
|
292
|
+
} else {
|
|
293
|
+
plural_word = `${last_word}s`;
|
|
294
|
+
}
|
|
295
|
+
return [...parts, plural_word].join("_");
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Remove empty, null, or undefined fields from an object
|
|
299
|
+
*/
|
|
300
|
+
static filterOutEmptyFields(obj) {
|
|
301
|
+
const filtered_object = {};
|
|
302
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
303
|
+
if (value !== null && value !== void 0 && !(typeof value === "string" && value.trim() === "") && !(Array.isArray(value) && value.length === 0)) {
|
|
304
|
+
filtered_object[key] = value;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return filtered_object;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Safely parse JSON input
|
|
311
|
+
*/
|
|
312
|
+
static toJson(json_input) {
|
|
313
|
+
try {
|
|
314
|
+
if (!json_input) {
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
if (typeof json_input === "string") {
|
|
318
|
+
return JSON.parse(json_input);
|
|
319
|
+
}
|
|
320
|
+
if (typeof json_input === "object") {
|
|
321
|
+
return json_input;
|
|
322
|
+
}
|
|
323
|
+
return null;
|
|
324
|
+
} catch {
|
|
325
|
+
return null;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Calculate pagination offset and limit
|
|
330
|
+
*/
|
|
331
|
+
static calculatePaginationOffset(page, size) {
|
|
332
|
+
const page_number = page > 0 ? page - 1 : 0;
|
|
333
|
+
const adjusted_size = size > 200 ? 200 : size;
|
|
334
|
+
const limit = adjusted_size || 10;
|
|
335
|
+
const offset = page_number * limit;
|
|
336
|
+
return { limit, offset };
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Format paginated response
|
|
340
|
+
*/
|
|
341
|
+
static formatPaginatedResponse(page, limit, data) {
|
|
342
|
+
const { count: total_items, rows: records } = data;
|
|
343
|
+
const current_page = page || 0;
|
|
344
|
+
const total_pages = Math.ceil(total_items / limit);
|
|
345
|
+
return {
|
|
346
|
+
total_items,
|
|
347
|
+
records,
|
|
348
|
+
total_pages,
|
|
349
|
+
current_page
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Compare two records and detect changes
|
|
354
|
+
*/
|
|
355
|
+
static detectChanges(old_record = {}, new_record = {}, keys_to_check) {
|
|
356
|
+
const structured_diff = {};
|
|
357
|
+
const all_keys = keys_to_check ?? Object.keys(new_record);
|
|
358
|
+
for (const key of all_keys) {
|
|
359
|
+
const old_value = old_record[key];
|
|
360
|
+
const new_value = new_record[key];
|
|
361
|
+
if (old_value == new_value) {
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
const formatted_old = typeof old_value === "object" && old_value !== null ? JSON.stringify(old_value) : String(old_value ?? "null");
|
|
365
|
+
const formatted_new = typeof new_value === "object" && new_value !== null ? JSON.stringify(new_value) : String(new_value ?? "null");
|
|
366
|
+
structured_diff[key] = {
|
|
367
|
+
old: formatted_old,
|
|
368
|
+
new: formatted_new
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
const readable_changes = Object.entries(
|
|
372
|
+
structured_diff
|
|
373
|
+
).map(
|
|
374
|
+
([key, value]) => `${key} changed from '${value.old}' \u2192 '${value.new}'`
|
|
375
|
+
).join("; ");
|
|
376
|
+
return {
|
|
377
|
+
readable: readable_changes || "No significant changes detected",
|
|
378
|
+
structured: structured_diff
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Normalize social links object keys
|
|
383
|
+
*/
|
|
384
|
+
static formatLinksObject(links) {
|
|
385
|
+
const formatted_links = {};
|
|
386
|
+
for (const [key, value] of Object.entries(links)) {
|
|
387
|
+
const normalized_key = key.toLowerCase().endsWith("_link") ? key.toLowerCase() : `${key.toLowerCase()}_link`;
|
|
388
|
+
formatted_links[normalized_key] = value;
|
|
389
|
+
}
|
|
390
|
+
return formatted_links;
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
var input_transformer_util_default = InputTransformerUtil;
|
|
394
|
+
|
|
395
|
+
// src/utils/input_validator_util.ts
|
|
396
|
+
import fs3 from "fs";
|
|
397
|
+
import dayjs2 from "dayjs";
|
|
398
|
+
import isSameOrAfter from "dayjs/plugin/isSameOrAfter";
|
|
399
|
+
import bcrypt2 from "bcrypt";
|
|
400
|
+
import axios3 from "axios";
|
|
401
|
+
|
|
402
|
+
// src/utils/env_manager_util.ts
|
|
403
|
+
import fs2 from "fs";
|
|
404
|
+
import path3 from "path";
|
|
405
|
+
import yaml from "js-yaml";
|
|
406
|
+
import axios2 from "axios";
|
|
407
|
+
var EnvManagerUtil = class _EnvManagerUtil {
|
|
408
|
+
name = "env_manager_util";
|
|
409
|
+
env_file_name = "env.yaml";
|
|
410
|
+
static instance;
|
|
411
|
+
yaml_env_file_path;
|
|
412
|
+
logger;
|
|
413
|
+
env_data;
|
|
414
|
+
// 🔒 Private constructor
|
|
415
|
+
constructor() {
|
|
416
|
+
this.env_file_name = this.getEnvFileName();
|
|
417
|
+
this.yaml_env_file_path = path3.join(ENV_VAR_DIR, this.env_file_name);
|
|
418
|
+
this.logger = new logger_util_default(this.name);
|
|
419
|
+
this.env_data = this.readENVData();
|
|
420
|
+
}
|
|
421
|
+
// Method to get env file name
|
|
422
|
+
getEnvFileName() {
|
|
423
|
+
if (process?.env?.MODE === "development") {
|
|
424
|
+
return "env.yaml";
|
|
425
|
+
} else if (process?.env?.MODE === "staging") {
|
|
426
|
+
return "staging_env.yaml";
|
|
427
|
+
} else if (process?.env?.MODE === "production") {
|
|
428
|
+
return "production_env.yaml";
|
|
429
|
+
} else {
|
|
430
|
+
return "env.yaml";
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
// ✅ Global access point
|
|
434
|
+
static getInstance() {
|
|
435
|
+
if (!_EnvManagerUtil.instance) {
|
|
436
|
+
_EnvManagerUtil.instance = new _EnvManagerUtil();
|
|
437
|
+
}
|
|
438
|
+
return _EnvManagerUtil.instance;
|
|
439
|
+
}
|
|
440
|
+
// Read environment data from YAML
|
|
441
|
+
readENVData() {
|
|
442
|
+
try {
|
|
443
|
+
if (!fs2.existsSync(this.yaml_env_file_path)) {
|
|
444
|
+
this.logger.info(`YAML file not found at: ${this.yaml_env_file_path}`);
|
|
445
|
+
return {};
|
|
446
|
+
}
|
|
447
|
+
const file_content = fs2.readFileSync(this.yaml_env_file_path, "utf8");
|
|
448
|
+
return yaml.load(file_content) || {};
|
|
449
|
+
} catch (error) {
|
|
450
|
+
this.logger.error(`${this.name} - readENVData`, { error });
|
|
451
|
+
return {};
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
// Get env var from YAML → process.env → default
|
|
455
|
+
getEnvVar(key, default_value) {
|
|
456
|
+
if (key in this.env_data) {
|
|
457
|
+
return this.env_data[key];
|
|
458
|
+
}
|
|
459
|
+
if (key in process.env) {
|
|
460
|
+
return process.env[key];
|
|
461
|
+
}
|
|
462
|
+
return default_value;
|
|
463
|
+
}
|
|
464
|
+
// Fetch remote env variables and merge
|
|
465
|
+
async fetchRemoteEnv(url) {
|
|
466
|
+
try {
|
|
467
|
+
const response = await axios2.get(url);
|
|
468
|
+
if (typeof response.data === "object" && response.data !== null) {
|
|
469
|
+
this.env_data = { ...this.env_data, ...response.data };
|
|
470
|
+
this.logger.success("Remote env variables loaded.");
|
|
471
|
+
} else {
|
|
472
|
+
this.logger.error("Unexpected response format from remote env endpoint.");
|
|
473
|
+
}
|
|
474
|
+
} catch (error) {
|
|
475
|
+
this.logger.error(`${this.name} - fetchRemoteEnv`, { error });
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
};
|
|
479
|
+
var env_manager_util_default = EnvManagerUtil;
|
|
480
|
+
|
|
481
|
+
// src/utils/input_validator_util.ts
|
|
482
|
+
dayjs2.extend(isSameOrAfter);
|
|
483
|
+
var InputValidatorUtil = class _InputValidatorUtil {
|
|
484
|
+
static optional_field_regex = /^[a-zA-Z0-9_\-]+$/;
|
|
485
|
+
static name_regex_reg_exp = /^[A-Za-z.'\s/_-]*$/;
|
|
486
|
+
static namey_regex_reg_exp = /^[A-Za-z0-9.'\s,/_\-()&]*$/;
|
|
487
|
+
static email_regex_reg_exp = /^(?=.{1,255}$)[a-zA-Z0-9._%+-]{1,64}@[a-zA-Z0-9.-]{1,190}\.[a-zA-Z]{2,}$/i;
|
|
488
|
+
static tel_regex_reg_exp = /^[\s()+-]*([0-9][\s()+-]*){6,20}$/;
|
|
489
|
+
static pass_regex_reg_exp = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{6,}$/;
|
|
490
|
+
static url_regex_reg_exp = /^(https?:\/\/)?((localhost|[a-zA-Z0-9-_.]+)(:[0-9]{1,5})?)(\/[a-zA-Z0-9-._~:/?#@!$&'()*+,;=%]*)?$/;
|
|
491
|
+
static text_area_regex_reg_exp = /^(?=.*[a-zA-Z])[\p{L}\p{N}\p{P}\p{Zs}–—“”‘’]*$/u;
|
|
492
|
+
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;
|
|
493
|
+
static custom_uuid_regex_reg_exp = /^[A-Z0-9]{12}-[A-Z0-9]{12}-[A-Z0-9]{12}-[A-Z0-9]{12}$/;
|
|
494
|
+
static env_manager = env_manager_util_default.getInstance();
|
|
495
|
+
static isValidateIn = (value, allowed) => allowed.includes(value);
|
|
496
|
+
/** ✅ Check member roles */
|
|
497
|
+
static isAdmin(name) {
|
|
498
|
+
return ["SuperAdmin", "AdminI", "AdminT"].includes(name);
|
|
499
|
+
}
|
|
500
|
+
static isSuperAdmin(name) {
|
|
501
|
+
return name === "SuperAdmin";
|
|
502
|
+
}
|
|
503
|
+
static isLowerSnakeCase(str) {
|
|
504
|
+
return /^[a-z]+(_[a-z]+)*$/.test(str);
|
|
505
|
+
}
|
|
506
|
+
static isUpperPascalCase(str) {
|
|
507
|
+
return /^[A-Z][a-zA-Z]*$/.test(str);
|
|
508
|
+
}
|
|
509
|
+
static isEmpty(input) {
|
|
510
|
+
return !input || input.toString().trim() === "";
|
|
511
|
+
}
|
|
512
|
+
static isValidOptionalField(str) {
|
|
513
|
+
return this.optional_field_regex.test(str);
|
|
514
|
+
}
|
|
515
|
+
static isValidName(name) {
|
|
516
|
+
return this.name_regex_reg_exp.test(name);
|
|
517
|
+
}
|
|
518
|
+
static isValidNamey(name) {
|
|
519
|
+
return this.namey_regex_reg_exp.test(name);
|
|
520
|
+
}
|
|
521
|
+
static isValidEmail(email) {
|
|
522
|
+
return this.email_regex_reg_exp.test(email) && email.length <= 254;
|
|
523
|
+
}
|
|
524
|
+
static isValidPhoneNumber(tel) {
|
|
525
|
+
return this.tel_regex_reg_exp.test(tel);
|
|
526
|
+
}
|
|
527
|
+
static isValidPassword(password) {
|
|
528
|
+
return this.pass_regex_reg_exp.test(password);
|
|
529
|
+
}
|
|
530
|
+
static isDigit(input) {
|
|
531
|
+
return !isNaN(input);
|
|
532
|
+
}
|
|
533
|
+
static isValidInteger(input) {
|
|
534
|
+
return Number.isInteger(input) && input > 0;
|
|
535
|
+
}
|
|
536
|
+
static isValidFloat(input) {
|
|
537
|
+
return !isNaN(input) && parseFloat(input) > 0;
|
|
538
|
+
}
|
|
539
|
+
static isValidURLY(url) {
|
|
540
|
+
try {
|
|
541
|
+
new URL(url);
|
|
542
|
+
return true;
|
|
543
|
+
} catch (_) {
|
|
544
|
+
return false;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
static isValidURL(url) {
|
|
548
|
+
return this.url_regex_reg_exp.test(url) && this.isValidURLY(url);
|
|
549
|
+
}
|
|
550
|
+
static isBoolean(value) {
|
|
551
|
+
return typeof value === "boolean" || ["1", "0"].includes(String(value));
|
|
552
|
+
}
|
|
553
|
+
static isValidLongText(text) {
|
|
554
|
+
if (!text || typeof text !== "string") {
|
|
555
|
+
return false;
|
|
556
|
+
}
|
|
557
|
+
const forbidden_pattern = /[<>{};`]/;
|
|
558
|
+
if (forbidden_pattern.test(text)) {
|
|
559
|
+
return false;
|
|
560
|
+
}
|
|
561
|
+
return this.text_area_regex_reg_exp.test(text.trim());
|
|
562
|
+
}
|
|
563
|
+
static isValidUUID(uuid) {
|
|
564
|
+
return this.uuid_regex_reg_exp.test(uuid);
|
|
565
|
+
}
|
|
566
|
+
static isValidCustomUUID(uuid) {
|
|
567
|
+
return this.custom_uuid_regex_reg_exp.test(uuid);
|
|
568
|
+
}
|
|
569
|
+
static isArrayUnique(arr) {
|
|
570
|
+
return new Set(arr).size === arr.length;
|
|
571
|
+
}
|
|
572
|
+
static isValidFutureDate(date_string) {
|
|
573
|
+
const date = dayjs2(date_string);
|
|
574
|
+
return date.isValid() && date.isAfter(dayjs2());
|
|
575
|
+
}
|
|
576
|
+
static isValidDateAndDifference(input, unit = "years") {
|
|
577
|
+
if (!input) {
|
|
578
|
+
return null;
|
|
579
|
+
}
|
|
580
|
+
const date = dayjs2(input);
|
|
581
|
+
if (!date.isValid()) {
|
|
582
|
+
return null;
|
|
583
|
+
}
|
|
584
|
+
return { date, difference: dayjs2().diff(date, unit) };
|
|
585
|
+
}
|
|
586
|
+
/** ✅ Validate password hash */
|
|
587
|
+
static async isValidHashPassword(password, hash_password) {
|
|
588
|
+
if (!password || !hash_password) {
|
|
589
|
+
return false;
|
|
590
|
+
}
|
|
591
|
+
return await bcrypt2.compare(password, hash_password);
|
|
592
|
+
}
|
|
593
|
+
/** ✅ Check environment */
|
|
594
|
+
static isProduction() {
|
|
595
|
+
return _InputValidatorUtil?.env_manager?.env_data?.MODE === "production";
|
|
596
|
+
}
|
|
597
|
+
static isStaging() {
|
|
598
|
+
return _InputValidatorUtil?.env_manager?.env_data?.MODE === "staging";
|
|
599
|
+
}
|
|
600
|
+
static isDevelopment() {
|
|
601
|
+
return _InputValidatorUtil?.env_manager?.env_data?.MODE === "development";
|
|
602
|
+
}
|
|
603
|
+
/** ✅ Validate ReCaptcha */
|
|
604
|
+
static async isValidReCaptcha(recpatcha_token) {
|
|
605
|
+
const {
|
|
606
|
+
RECAPTCHA_SECRET_KEY,
|
|
607
|
+
RECPATHA_VERIFY_URL
|
|
608
|
+
} = _InputValidatorUtil?.env_manager?.env_data;
|
|
609
|
+
try {
|
|
610
|
+
const secret_key = RECAPTCHA_SECRET_KEY;
|
|
611
|
+
const url = RECPATHA_VERIFY_URL;
|
|
612
|
+
const params = { secret: secret_key, response: recpatcha_token };
|
|
613
|
+
const response = await axios3.post(url, null, { params });
|
|
614
|
+
return response.data.success;
|
|
615
|
+
} catch (error) {
|
|
616
|
+
console.error("reCAPTCHA verification failed:", error);
|
|
617
|
+
return false;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
// Method to check if a directory exists
|
|
621
|
+
static dirExists(directory, create_directory = false, return_dir_path = false) {
|
|
622
|
+
const exist = fs3.existsSync(directory);
|
|
623
|
+
if (!create_directory) {
|
|
624
|
+
return exist;
|
|
625
|
+
}
|
|
626
|
+
if (!exist) {
|
|
627
|
+
fs3.mkdirSync(directory);
|
|
628
|
+
}
|
|
629
|
+
return return_dir_path ? directory : true;
|
|
630
|
+
}
|
|
631
|
+
};
|
|
632
|
+
var input_validator_util_default = InputValidatorUtil;
|
|
633
|
+
|
|
634
|
+
// src/utils/sql_formatter_util.ts
|
|
635
|
+
var SqlFormatterUtil = class _SqlFormatterUtil {
|
|
636
|
+
// Basic ANSI color helpers
|
|
637
|
+
static AnsiColor = {
|
|
638
|
+
reset: "\x1B[0m",
|
|
639
|
+
cyan: (text) => `\x1B[36m${text}\x1B[0m`,
|
|
640
|
+
green: (text) => `\x1B[32m${text}\x1B[0m`,
|
|
641
|
+
yellow: (text) => `\x1B[33m${text}\x1B[0m`,
|
|
642
|
+
red: (text) => `\x1B[31m${text}\x1B[0m`
|
|
643
|
+
};
|
|
644
|
+
static sqlColors = {
|
|
645
|
+
SELECT: _SqlFormatterUtil.AnsiColor.cyan,
|
|
646
|
+
INSERT: _SqlFormatterUtil.AnsiColor.green,
|
|
647
|
+
UPDATE: _SqlFormatterUtil.AnsiColor.yellow,
|
|
648
|
+
DELETE: _SqlFormatterUtil.AnsiColor.red
|
|
649
|
+
};
|
|
650
|
+
/**
|
|
651
|
+
* Normalize SQL:
|
|
652
|
+
* - Collapse multiple whitespaces/newlines
|
|
653
|
+
* - Remove extra spaces inside parentheses
|
|
654
|
+
*/
|
|
655
|
+
static normalize(sql) {
|
|
656
|
+
return sql.replace(/\s+/g, " ").replace(/\(\s+/g, "(").replace(/\s+\)/g, ")").trim();
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* Colorize SQL keywords (SELECT, INSERT, UPDATE, DELETE)
|
|
660
|
+
*/
|
|
661
|
+
static colorize(sql) {
|
|
662
|
+
const first_word = sql.split(" ")[0].toUpperCase();
|
|
663
|
+
const colorFN = this.sqlColors[first_word];
|
|
664
|
+
return colorFN ? colorFN(sql) : sql;
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Full formatting for logging
|
|
668
|
+
*/
|
|
669
|
+
static format(sql) {
|
|
670
|
+
return this.colorize(this.normalize(sql));
|
|
671
|
+
}
|
|
672
|
+
};
|
|
673
|
+
var sql_formatter_util_default = SqlFormatterUtil;
|
|
674
|
+
|
|
675
|
+
// src/utils/server_util.ts
|
|
676
|
+
var ServerUtil = class {
|
|
677
|
+
name = "server_util";
|
|
678
|
+
logger = new logger_util_default(this.name);
|
|
679
|
+
port;
|
|
680
|
+
constructor(port) {
|
|
681
|
+
this.port = port || 4e3;
|
|
682
|
+
}
|
|
683
|
+
// Method to print app banner
|
|
684
|
+
printAppBanner(app_name) {
|
|
685
|
+
const raw = app_name.replace(/[-_]/g, " ");
|
|
686
|
+
const title = raw.toUpperCase();
|
|
687
|
+
const border_char = "\u2550";
|
|
688
|
+
const corner_tl = "\u2554";
|
|
689
|
+
const corner_tr = "\u2557";
|
|
690
|
+
const corner_bl = "\u255A";
|
|
691
|
+
const corner_br = "\u255D";
|
|
692
|
+
const side_char = "\u2551";
|
|
693
|
+
const padding = 4;
|
|
694
|
+
const content_width = title.length + padding * 2;
|
|
695
|
+
const border = border_char.repeat(content_width);
|
|
696
|
+
const line1 = `${corner_tl}${border}${corner_tr}`;
|
|
697
|
+
const line2 = `${side_char} ${" ".repeat(padding)}${title}${" ".repeat(padding)}${side_char} `;
|
|
698
|
+
const line3 = `${corner_bl}${border}${corner_br} `;
|
|
699
|
+
console.log("\n" + line1);
|
|
700
|
+
console.log(line2);
|
|
701
|
+
console.log(line3 + "\n");
|
|
702
|
+
}
|
|
703
|
+
// Method to handle server errors
|
|
704
|
+
onServerError(error) {
|
|
705
|
+
if (error.syscall !== "listen") {
|
|
706
|
+
this.logger.error("Unexpected server error", { error });
|
|
707
|
+
throw error;
|
|
708
|
+
}
|
|
709
|
+
const bind = `Port ${this.port}`;
|
|
710
|
+
switch (error.code) {
|
|
711
|
+
case "EACCES":
|
|
712
|
+
this.logger.error(`${bind} requires elevated privileges`);
|
|
713
|
+
process.exit(1);
|
|
714
|
+
break;
|
|
715
|
+
case "EADDRINUSE":
|
|
716
|
+
this.logger.error(`${bind} is already in use`);
|
|
717
|
+
process.exit(1);
|
|
718
|
+
break;
|
|
719
|
+
default:
|
|
720
|
+
throw error;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
// Method to handle server listening
|
|
724
|
+
onServerListening = (server) => {
|
|
725
|
+
this.printAppBanner("fibase-server-app");
|
|
726
|
+
const addr = server.address();
|
|
727
|
+
const bind = typeof addr === "string" ? `pipe ${addr}` : `port ${addr?.port}`;
|
|
728
|
+
this.logger.info(`Listening on ${bind}`);
|
|
729
|
+
};
|
|
730
|
+
};
|
|
731
|
+
var server_util_default = ServerUtil;
|
|
732
|
+
|
|
733
|
+
// src/utils/safe_execute_util.ts
|
|
734
|
+
var SafeExecuteUtil = class _SafeExecuteUtil {
|
|
735
|
+
// Store instances by class constructor (WeakMap ensures GC can clean up)
|
|
736
|
+
static instances = /* @__PURE__ */ new WeakMap();
|
|
737
|
+
// Store instances by string keys (Map keeps strong references)
|
|
738
|
+
static named_insatnces = /* @__PURE__ */ new Map();
|
|
739
|
+
static setInstance(key, instance) {
|
|
740
|
+
_SafeExecuteUtil.instances.set(key, instance);
|
|
741
|
+
}
|
|
742
|
+
/** Set instance by string key */
|
|
743
|
+
static setNamedInstance(key, instance) {
|
|
744
|
+
_SafeExecuteUtil.named_insatnces.set(key, instance);
|
|
745
|
+
}
|
|
746
|
+
static getInstance(key, fallback) {
|
|
747
|
+
return _SafeExecuteUtil.instances.get(key) ?? fallback;
|
|
748
|
+
}
|
|
749
|
+
/** Get instance by string key */
|
|
750
|
+
static getNamedInstance(key, fallback) {
|
|
751
|
+
return _SafeExecuteUtil.named_insatnces.get(key) ?? fallback;
|
|
752
|
+
}
|
|
753
|
+
// Method to Safely stringify any object for logging
|
|
754
|
+
static safeStringify(obj) {
|
|
755
|
+
try {
|
|
756
|
+
return JSON.stringify(obj);
|
|
757
|
+
} catch {
|
|
758
|
+
return "[Unserializable Params]";
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
// 🔹 Method to Execution time logger
|
|
762
|
+
static logExecutionTime(start, class_name, method_name, logger) {
|
|
763
|
+
const [seconds, nanoseconds] = process.hrtime(start);
|
|
764
|
+
const ms = (seconds * 1e3 + nanoseconds / 1e6).toFixed(2);
|
|
765
|
+
logger.info(`[${class_name}] \u23F1\uFE0F ${method_name} executed in ${ms}ms`);
|
|
766
|
+
}
|
|
767
|
+
// Method to handle on error action
|
|
768
|
+
static handleOnErrorAction(error, strategy, default_value, controller_response) {
|
|
769
|
+
if (strategy === 3 /* CONTROLLER_ERROR */ && controller_response?.errResponse) {
|
|
770
|
+
return controller_response?.errResponse?.(500, "invalid_error_request");
|
|
771
|
+
}
|
|
772
|
+
switch (strategy) {
|
|
773
|
+
case 0 /* RETURN_DEFAULT */:
|
|
774
|
+
return default_value;
|
|
775
|
+
case 1 /* EXIT_PROCESS */:
|
|
776
|
+
process.exit(1);
|
|
777
|
+
case 2 /* THROW_ERROR */:
|
|
778
|
+
throw error;
|
|
779
|
+
}
|
|
780
|
+
return;
|
|
781
|
+
}
|
|
782
|
+
// 🔹 Method to Unifysafe execution wrapper (normal methods)
|
|
783
|
+
static createSafeFunction(class_name, method_name, original_method, strategy, default_value) {
|
|
784
|
+
return async function(...args) {
|
|
785
|
+
const class_instance = _SafeExecuteUtil.getNamedInstance(class_name, this);
|
|
786
|
+
const logger = class_instance?.logger || new logger_util_default(class_name);
|
|
787
|
+
const method_params = args;
|
|
788
|
+
try {
|
|
789
|
+
return await original_method.apply(class_instance, method_params);
|
|
790
|
+
} catch (error) {
|
|
791
|
+
const safely_stringified_error = _SafeExecuteUtil.safeStringify(error);
|
|
792
|
+
logger.error(`[${class_name}] \u274C Error in method ${method_name}`, { method_params, error, safely_stringified_error });
|
|
793
|
+
_SafeExecuteUtil.handleOnErrorAction(error, strategy, default_value);
|
|
794
|
+
}
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
// 🔹 Unified safe execution wrapper with timing (for controller/service)
|
|
798
|
+
static createTimedSafeFunction(class_name, method_name, original_method, strategy, default_value) {
|
|
799
|
+
return async function(...args) {
|
|
800
|
+
const class_instance = _SafeExecuteUtil.getNamedInstance(class_name, this);
|
|
801
|
+
const logger = class_instance?.logger || new logger_util_default(class_name);
|
|
802
|
+
const start_time = process.hrtime();
|
|
803
|
+
const method_params = args;
|
|
804
|
+
const controller_response = args && args.length ? args[1] : void 0;
|
|
805
|
+
try {
|
|
806
|
+
const result = await original_method.apply(class_instance, args);
|
|
807
|
+
return result;
|
|
808
|
+
} catch (error) {
|
|
809
|
+
const safely_stringified_error = _SafeExecuteUtil.safeStringify(error);
|
|
810
|
+
logger.error(`[${class_name}] \u274C Error in method ${method_name}`, { method_params, error, safely_stringified_error });
|
|
811
|
+
_SafeExecuteUtil.handleOnErrorAction(error, strategy, default_value, controller_response);
|
|
812
|
+
} finally {
|
|
813
|
+
_SafeExecuteUtil.logExecutionTime(start_time, class_name, method_name, logger);
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
// Decorator Method to handle wrapping cclass methods
|
|
818
|
+
static applySafeWrapper(target, class_name, property_key, descriptor, strategy, timed, default_value) {
|
|
819
|
+
if (typeof descriptor.value !== "function") {
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
descriptor.value = timed ? _SafeExecuteUtil.createTimedSafeFunction(
|
|
823
|
+
class_name,
|
|
824
|
+
String(property_key),
|
|
825
|
+
descriptor.value,
|
|
826
|
+
strategy,
|
|
827
|
+
default_value
|
|
828
|
+
) : _SafeExecuteUtil.createSafeFunction(
|
|
829
|
+
class_name,
|
|
830
|
+
String(property_key),
|
|
831
|
+
descriptor.value,
|
|
832
|
+
strategy,
|
|
833
|
+
default_value
|
|
834
|
+
);
|
|
835
|
+
}
|
|
836
|
+
// Decorator method to handle controller methods
|
|
837
|
+
static safeExecuteController(class_name) {
|
|
838
|
+
return function(target, property_key, descriptor) {
|
|
839
|
+
return _SafeExecuteUtil.applySafeWrapper(
|
|
840
|
+
target,
|
|
841
|
+
class_name,
|
|
842
|
+
property_key,
|
|
843
|
+
descriptor,
|
|
844
|
+
3 /* CONTROLLER_ERROR */,
|
|
845
|
+
true
|
|
846
|
+
);
|
|
847
|
+
};
|
|
848
|
+
}
|
|
849
|
+
// Decorator Method to handle service methods
|
|
850
|
+
static safeExecuteService(class_name, default_value) {
|
|
851
|
+
return function(target, property_key, descriptor) {
|
|
852
|
+
return _SafeExecuteUtil.applySafeWrapper(
|
|
853
|
+
target,
|
|
854
|
+
class_name,
|
|
855
|
+
property_key,
|
|
856
|
+
descriptor,
|
|
857
|
+
0 /* RETURN_DEFAULT */,
|
|
858
|
+
true,
|
|
859
|
+
default_value
|
|
860
|
+
);
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
// Decorator Method to wrap method with retrun value
|
|
864
|
+
static safeExecuteReturn(class_name, default_value) {
|
|
865
|
+
return function(target, property_key, descriptor) {
|
|
866
|
+
return _SafeExecuteUtil.applySafeWrapper(
|
|
867
|
+
target,
|
|
868
|
+
class_name,
|
|
869
|
+
property_key,
|
|
870
|
+
descriptor,
|
|
871
|
+
0 /* RETURN_DEFAULT */,
|
|
872
|
+
false,
|
|
873
|
+
default_value
|
|
874
|
+
);
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
// Decorator Method to wrap method with retrun value
|
|
878
|
+
static safeExecuteTransaction(class_name, default_value) {
|
|
879
|
+
return function(target, property_key, descriptor) {
|
|
880
|
+
return _SafeExecuteUtil.applySafeWrapper(
|
|
881
|
+
target,
|
|
882
|
+
class_name,
|
|
883
|
+
property_key,
|
|
884
|
+
descriptor,
|
|
885
|
+
0 /* RETURN_DEFAULT */,
|
|
886
|
+
false,
|
|
887
|
+
default_value
|
|
888
|
+
);
|
|
889
|
+
};
|
|
890
|
+
}
|
|
891
|
+
// Decorator method to wrap method with void return
|
|
892
|
+
static safeExecute(class_name) {
|
|
893
|
+
return function(target, property_key, descriptor) {
|
|
894
|
+
return _SafeExecuteUtil.applySafeWrapper(
|
|
895
|
+
target,
|
|
896
|
+
class_name,
|
|
897
|
+
property_key,
|
|
898
|
+
descriptor,
|
|
899
|
+
0 /* RETURN_DEFAULT */,
|
|
900
|
+
false
|
|
901
|
+
);
|
|
902
|
+
};
|
|
903
|
+
}
|
|
904
|
+
// Decorator method to wrap method with void return
|
|
905
|
+
static safeExecuteExit(class_name) {
|
|
906
|
+
return function(target, property_key, descriptor) {
|
|
907
|
+
return _SafeExecuteUtil.applySafeWrapper(
|
|
908
|
+
target,
|
|
909
|
+
class_name,
|
|
910
|
+
property_key,
|
|
911
|
+
descriptor,
|
|
912
|
+
1 /* EXIT_PROCESS */,
|
|
913
|
+
false
|
|
914
|
+
);
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
// Decorator method to wrap method with void return
|
|
918
|
+
static safeExecuteThrow(class_name) {
|
|
919
|
+
return function(target, property_key, descriptor) {
|
|
920
|
+
return _SafeExecuteUtil.applySafeWrapper(
|
|
921
|
+
target,
|
|
922
|
+
class_name,
|
|
923
|
+
property_key,
|
|
924
|
+
descriptor,
|
|
925
|
+
2 /* THROW_ERROR */,
|
|
926
|
+
false
|
|
927
|
+
);
|
|
928
|
+
};
|
|
929
|
+
}
|
|
930
|
+
};
|
|
931
|
+
var safe_execute_util_default = SafeExecuteUtil;
|
|
932
|
+
|
|
933
|
+
// src/utils/cache_util.ts
|
|
934
|
+
var InMemoryCache = class {
|
|
935
|
+
store = /* @__PURE__ */ new Map();
|
|
936
|
+
/**
|
|
937
|
+
* Set a cache value with TTL (ms)
|
|
938
|
+
*/
|
|
939
|
+
set(key, value, ttl_ms) {
|
|
940
|
+
if (!key) return;
|
|
941
|
+
const expires_at = Date.now() + ttl_ms;
|
|
942
|
+
this.store.set(key, { value, expires_at });
|
|
943
|
+
}
|
|
944
|
+
/**
|
|
945
|
+
* Get a cache value (returns undefined if missing or expired)
|
|
946
|
+
*/
|
|
947
|
+
get(key) {
|
|
948
|
+
const entry = this.store.get(key);
|
|
949
|
+
if (!entry) return void 0;
|
|
950
|
+
if (Date.now() > entry.expires_at) {
|
|
951
|
+
this.store.delete(key);
|
|
952
|
+
return void 0;
|
|
953
|
+
}
|
|
954
|
+
return entry.value;
|
|
955
|
+
}
|
|
956
|
+
/**
|
|
957
|
+
* Check if a key exists and is valid
|
|
958
|
+
*/
|
|
959
|
+
has(key) {
|
|
960
|
+
return this.get(key) !== void 0;
|
|
961
|
+
}
|
|
962
|
+
/**
|
|
963
|
+
* Update an existing cache entry (keeps old TTL)
|
|
964
|
+
*/
|
|
965
|
+
update(key, value) {
|
|
966
|
+
const entry = this.store.get(key);
|
|
967
|
+
if (!entry) return false;
|
|
968
|
+
if (Date.now() > entry.expires_at) {
|
|
969
|
+
this.store.delete(key);
|
|
970
|
+
return false;
|
|
971
|
+
}
|
|
972
|
+
this.store.set(key, { ...entry, value });
|
|
973
|
+
return true;
|
|
974
|
+
}
|
|
975
|
+
/**
|
|
976
|
+
* Delete a single cache entry
|
|
977
|
+
*/
|
|
978
|
+
delete(key) {
|
|
979
|
+
return this.store.delete(key);
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* Clear entire cache
|
|
983
|
+
*/
|
|
984
|
+
clear() {
|
|
985
|
+
this.store.clear();
|
|
986
|
+
}
|
|
987
|
+
/**
|
|
988
|
+
* Manually expire a key immediately
|
|
989
|
+
*/
|
|
990
|
+
expire(key) {
|
|
991
|
+
this.store.delete(key);
|
|
992
|
+
}
|
|
993
|
+
/**
|
|
994
|
+
* Cleanup expired entries (optional call)
|
|
995
|
+
*/
|
|
996
|
+
cleanup() {
|
|
997
|
+
const now = Date.now();
|
|
998
|
+
for (const [key, entry] of this.store.entries()) {
|
|
999
|
+
if (now > entry.expires_at) {
|
|
1000
|
+
this.store.delete(key);
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
/**
|
|
1005
|
+
* Cache size (for metrics)
|
|
1006
|
+
*/
|
|
1007
|
+
size() {
|
|
1008
|
+
return this.store.size;
|
|
1009
|
+
}
|
|
1010
|
+
};
|
|
1011
|
+
var cache_util_default = InMemoryCache;
|
|
1012
|
+
|
|
1013
|
+
export {
|
|
1014
|
+
SCHEMAS_DIR,
|
|
1015
|
+
SCHEMA_SNAPSHOTS_DIR,
|
|
1016
|
+
MIGRATIONS_DIR,
|
|
1017
|
+
SEEDERS_DIR,
|
|
1018
|
+
SEQUELIZE_META_TABLE_NAME,
|
|
1019
|
+
SEQUELIZE_SEEDER_META_TABLE_NAME,
|
|
1020
|
+
logger_util_default,
|
|
1021
|
+
input_transformer_util_default,
|
|
1022
|
+
env_manager_util_default,
|
|
1023
|
+
input_validator_util_default,
|
|
1024
|
+
sql_formatter_util_default,
|
|
1025
|
+
server_util_default,
|
|
1026
|
+
safe_execute_util_default,
|
|
1027
|
+
cache_util_default
|
|
1028
|
+
};
|
|
1029
|
+
//# sourceMappingURL=chunk-BK6YPN2O.js.map
|