A very performant and light (2mb in memory) link shortener and tracker. Written in Rust and React and uses Postgres/SQLite.
at master 2.4 kB view raw
1import axios from 'axios'; 2import { CreateLinkRequest, Link, AuthResponse, ClickStats, SourceStats } from '../types/api'; 3 4// Create axios instance with default config 5const api = axios.create({ 6 baseURL: '/api', 7}); 8 9// Add a request interceptor to add the auth token to all requests 10api.interceptors.request.use((config) => { 11 const token = localStorage.getItem('token'); 12 if (token) { 13 config.headers.Authorization = `Bearer ${token}`; 14 } 15 return config; 16}); 17 18api.interceptors.response.use( 19 (response) => response, 20 (error) => { 21 if (error.response?.status === 401) { 22 localStorage.removeItem('token'); 23 localStorage.removeItem('user'); 24 25 window.dispatchEvent(new Event('unauthorized')); 26 } 27 return Promise.reject(error); 28 } 29); 30 31 32// Auth endpoints 33export const login = async (email: string, password: string) => { 34 const response = await api.post<AuthResponse>('/auth/login', { 35 email, 36 password, 37 }); 38 return response.data; 39}; 40 41export const register = async (email: string, password: string, adminToken: string) => { 42 const response = await api.post<AuthResponse>('/auth/register', { 43 email, 44 password, 45 admin_token: adminToken, 46 }); 47 return response.data; 48}; 49 50// Protected endpoints 51export const createShortLink = async (data: CreateLinkRequest) => { 52 const response = await api.post<Link>('/shorten', data); 53 return response.data; 54}; 55 56export const getAllLinks = async () => { 57 const response = await api.get<Link[]>('/links'); 58 return response.data; 59}; 60 61export const editLink = async (id: number, data: Partial<CreateLinkRequest>) => { 62 const response = await api.patch<Link>(`/links/${id}`, data); 63 return response.data; 64}; 65 66 67export const deleteLink = async (id: number) => { 68 await api.delete(`/links/${id}`); 69}; 70 71export const getLinkClickStats = async (id: number) => { 72 try { 73 const response = await api.get<ClickStats[]>(`/links/${id}/clicks`); 74 return response.data; 75 } catch (error) { 76 console.error('Error fetching click stats:', error); 77 throw error; 78 } 79}; 80 81export const getLinkSourceStats = async (id: number) => { 82 try { 83 const response = await api.get<SourceStats[]>(`/links/${id}/sources`); 84 return response.data; 85 } catch (error) { 86 console.error('Error fetching source stats:', error); 87 throw error; 88 } 89}; 90 91 92export const checkFirstUser = async () => { 93 const response = await api.get<{ isFirstUser: boolean }>('/auth/check-first-user'); 94 return response.data.isFirstUser; 95}; 96 97export { api };