feat: enhance error handling and configuration validation
Some checks failed
CI / lint-and-test (push) Failing after 27s
Some checks failed
CI / lint-and-test (push) Failing after 27s
- Added a global exception handler to log unhandled exceptions and return a generic 500 JSON response without exposing details to the client. - Updated the configuration to validate the `DATABASE_URL` format, ensuring it starts with `sqlite://` or `postgresql://`, and log warnings for invalid formats. - Introduced safe parsing for numeric environment variables (`HTTP_PORT`, `INIT_DATA_MAX_AGE_SECONDS`) with defaults on invalid values, including logging warnings for out-of-range values. - Enhanced the duty schedule parser to enforce limits on the number of schedule rows and the length of full names and duty strings, raising appropriate errors when exceeded. - Updated internationalization messages to include generic error responses for import failures and parsing issues, improving user experience. - Added unit tests to verify the new error handling and configuration validation behaviors.
This commit is contained in:
@@ -40,6 +40,7 @@ export const MESSAGES = {
|
||||
"event_type.duty": "Duty",
|
||||
"event_type.unavailable": "Unavailable",
|
||||
"event_type.vacation": "Vacation",
|
||||
"event_type.other": "Other",
|
||||
"duty.now_on_duty": "On duty now",
|
||||
"duty.none_this_month": "No duties this month.",
|
||||
"duty.today": "Today",
|
||||
@@ -96,6 +97,7 @@ export const MESSAGES = {
|
||||
"event_type.duty": "Дежурство",
|
||||
"event_type.unavailable": "Недоступен",
|
||||
"event_type.vacation": "Отпуск",
|
||||
"event_type.other": "Другое",
|
||||
"duty.now_on_duty": "Сейчас дежурит",
|
||||
"duty.none_this_month": "В этом месяце дежурств нет.",
|
||||
"duty.today": "Сегодня",
|
||||
@@ -161,10 +163,30 @@ export function getLang() {
|
||||
* @param {Record<string, string>} [params] - e.g. { time: '14:00' }
|
||||
* @returns {string}
|
||||
*/
|
||||
/**
|
||||
* Resolve event_type.* key with fallback: unknown types use event_type.duty or event_type.other.
|
||||
* @param {'ru'|'en'} lang
|
||||
* @param {string} key
|
||||
* @returns {string}
|
||||
*/
|
||||
function tEventType(lang, key) {
|
||||
const dict = MESSAGES[lang] || MESSAGES.en;
|
||||
const enDict = MESSAGES.en;
|
||||
let s = dict[key];
|
||||
if (s === undefined) s = enDict[key];
|
||||
if (s === undefined) {
|
||||
s = dict["event_type.other"] || enDict["event_type.other"] || enDict["event_type.duty"] || key;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
export function t(lang, key, params = {}) {
|
||||
const dict = MESSAGES[lang] || MESSAGES.en;
|
||||
let s = dict[key];
|
||||
if (s === undefined) s = MESSAGES.en[key];
|
||||
if (s === undefined && key.startsWith("event_type.")) {
|
||||
return tEventType(lang, key);
|
||||
}
|
||||
if (s === undefined) return key;
|
||||
Object.keys(params).forEach((k) => {
|
||||
s = s.replace(new RegExp("\\{" + k + "\\}", "g"), params[k]);
|
||||
|
||||
Reference in New Issue
Block a user