📦 EqualifyEverything / equalify-hub

📄 utils.ts · 86 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86// Common utility functions shared across components

export function escapeHtml(text: string): string {
    if (!text) return '';
    return text
        .replace(/&/g, '&')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;');
}

export function formatNumber(num: number): string {
    if (num >= 1000000) return (num / 1000000).toFixed(1) + 'm';
    if (num >= 1000) return (num / 1000).toFixed(1) + 'k';
    return num.toString();
}

export function timeAgo(dateStr: string): string {
    const date = new Date(dateStr);
    const now = new Date();
    const diffMs = now.getTime() - date.getTime();
    const diffMins = Math.floor(diffMs / (1000 * 60));
    const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
    const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
    
    if (diffMins < 1) return 'just now';
    if (diffMins < 60) return `${diffMins}m ago`;
    if (diffHours < 24) return `${diffHours}h ago`;
    if (diffDays < 30) return `${diffDays}d ago`;
    return `${Math.floor(diffDays / 30)}mo ago`;
}

export function getLanguageColor(lang: string): string {
    const colors: Record<string, string> = {
        'JavaScript': '#f1e05a',
        'TypeScript': '#3178c6',
        'Python': '#3572A5',
        'Java': '#b07219',
        'C++': '#f34b7d',
        'C': '#555555',
        'C#': '#178600',
        'Go': '#00ADD8',
        'Rust': '#dea584',
        'Ruby': '#701516',
        'PHP': '#4F5D95',
        'Swift': '#F05138',
        'Kotlin': '#A97BFF',
        'Dart': '#00B4AB',
        'HTML': '#e34c26',
        'CSS': '#563d7c',
        'Shell': '#89e051',
        'Vue': '#41b883',
        'Svelte': '#ff3e00',
    };
    return colors[lang] || '#8b949e';
}

// Parse form body - handles base64 encoding from API Gateway
export function parseFormBody(event: any): URLSearchParams {
    let body = event.body || '';
    if (event.isBase64Encoded && typeof body === 'string') {
        body = Buffer.from(body, 'base64').toString('utf-8');
    }
    if (typeof body === 'object') {
        body = event.rawBody || '';
        if (event.isBase64Encoded && typeof body === 'string') {
            body = Buffer.from(body, 'base64').toString('utf-8');
        }
    }
    return new URLSearchParams(body);
}

// Get visitor IP from request headers
export function getVisitorIp(headers: Record<string, any>): string {
    const getHeader = (name: string): string => {
        const lower = name.toLowerCase();
        for (const [key, value] of Object.entries(headers || {})) {
            if (key.toLowerCase() === lower) return String(value || '');
        }
        return '';
    };
    return getHeader('x-forwarded-for')?.split(',')[0]?.trim() || 
           getHeader('cloudfront-viewer-address')?.split(':')[0] || 
           'Unknown';
}