const FIELD_LABELS: Record = { title: 'عنوان', name: 'نام', firstName: 'نام', lastName: 'نام خانوادگی', fullName: 'نام', description: 'توضیحات', body: 'متن', mobile: 'موبایل', phone: 'تلفن', email: 'ایمیل', status: 'وضعیت', stageId: 'مرحله', priority: 'اولویت', dueAt: 'موعد', amount: 'مبلغ', subject: 'موضوع', type: 'نوع', city: 'شهر', address: 'آدرس', notes: 'یادداشت', contactName: 'نام مخاطب', }; const SECRET = /password|token|secret|otp|pin/i; function textOf(value: unknown) { if (typeof value === 'string') return value.trim().replace(/\s+/g, ' '); if (typeof value === 'number' || typeof value === 'boolean') return String(value); return ''; } function labelOf(source: unknown) { if (!source || typeof source !== 'object' || Array.isArray(source)) return ''; const body = source as Record; const person = [textOf(body.firstName), textOf(body.lastName)].filter(Boolean).join(' '); return ( person || textOf(body.title) || textOf(body.name) || textOf(body.subject) || textOf(body.fullName) ).slice(0, 120); } function changesOf(source: unknown) { if (!source || typeof source !== 'object' || Array.isArray(source)) return ''; const bits: string[] = []; for (const [key, value] of Object.entries(source as Record)) { if (SECRET.test(key)) continue; const name = FIELD_LABELS[key]; if (!name) continue; if (key.endsWith('Id')) { bits.push(name); } else { const text = textOf(value).slice(0, 40); if (!text) continue; bits.push(`${name}: ${text}`); } if (bits.length >= 4) break; } return bits.join('، '); } export function auditStory( method: string, requestBody: unknown, responseBody: unknown, ) { const label = labelOf(responseBody) || labelOf(requestBody); const detail = method === 'DELETE' ? '' : changesOf(requestBody); const summary = [label, detail].filter(Boolean).join(' — ').slice(0, 500); return { label, detail: detail.slice(0, 240), summary, }; }