"chore: update frontend dev script to include lint checks and add ESLint config file"

This commit is contained in:
louiscklaw
2025-06-04 02:35:32 +08:00
parent c0fad42f0a
commit 22fb620eef
48 changed files with 3315 additions and 97 deletions

View File

@@ -0,0 +1,92 @@
import axios, { endpoints } from '../../lib/axios';
import { setSession } from './utils';
import { JWT_STORAGE_KEY } from './constant';
// ----------------------------------------------------------------------
export type SignInParams = {
email: string;
password: string;
};
export type SignUpParams = {
email: string;
password: string;
firstName: string;
lastName: string;
};
const ERR_ACCESS_TOKEN_NOT_FOUND = `Access token not found in response`;
/** **************************************
* Sign in
*************************************** */
export const signInWithPassword = async ({
email,
password,
}: SignInParams): Promise<string | null> => {
try {
const params = { email, password };
const res = await axios.post(endpoints.auth.signIn, params);
const { accessToken } = res.data;
console.log({ t: res.data });
if (!accessToken) {
throw new Error(ERR_ACCESS_TOKEN_NOT_FOUND);
}
// setSession(accessToken);
return accessToken;
} catch (error) {
console.error('Error during sign in:', error);
throw error;
}
};
/** **************************************
* Sign up
*************************************** */
export const signUp = async ({
email,
password,
firstName,
lastName,
}: SignUpParams): Promise<void> => {
const params = {
email,
password,
firstName,
lastName,
};
try {
const res = await axios.post(endpoints.auth.signUp, params);
const { accessToken } = res.data;
if (!accessToken) {
throw new Error('Access token not found in response');
}
sessionStorage.setItem(JWT_STORAGE_KEY, accessToken);
} catch (error) {
console.error('Error during sign up:', error);
throw error;
}
};
/** **************************************
* Sign out
*************************************** */
export const signOut = async (): Promise<void> => {
try {
await setSession(null);
} catch (error) {
console.error('Error during sign out:', error);
throw error;
}
};

View File

@@ -0,0 +1 @@
export const JWT_STORAGE_KEY = 'jwt_access_token';

View File

@@ -0,0 +1,97 @@
// import { paths } from 'src/routes/paths';
import axios from '../../lib/axios';
import { JWT_STORAGE_KEY } from './constant.js';
import paths from '../../paths.js';
// ----------------------------------------------------------------------
export function jwtDecode(token: string) {
try {
if (!token) return null;
const parts = token.split('.');
if (parts.length < 2) {
throw new Error('Invalid token!');
}
const base64Url = parts[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const decoded = JSON.parse(atob(base64));
return decoded;
} catch (error) {
console.error('Error decoding token:', error);
throw error;
}
}
// ----------------------------------------------------------------------
export function isValidToken(accessToken: string) {
if (!accessToken) {
return false;
}
try {
const decoded = jwtDecode(accessToken);
if (!decoded || !('exp' in decoded)) {
return false;
}
const currentTime = Date.now() / 1000;
return decoded.exp > currentTime;
} catch (error) {
console.error('Error during token validation:', error);
return false;
}
}
// ----------------------------------------------------------------------
export function tokenExpired(exp: number) {
const currentTime = Date.now();
const timeLeft = exp * 1000 - currentTime;
setTimeout(() => {
try {
alert('Token expired!');
sessionStorage.removeItem(JWT_STORAGE_KEY);
window.location.href = paths.SIGN_IN;
} catch (error) {
console.error('Error during token expiration:', error);
throw error;
}
}, timeLeft);
}
// ----------------------------------------------------------------------
const INVALID_ACCESS_TOKEN = 'Invalid access token!';
export async function setSession(accessToken: string | null) {
try {
if (accessToken) {
sessionStorage.setItem(JWT_STORAGE_KEY, accessToken);
axios.defaults.headers.common.Authorization = `Bearer ${accessToken}`;
const decodedToken = jwtDecode(accessToken); // ~3 days by minimals server
if (decodedToken && 'exp' in decodedToken) {
tokenExpired(decodedToken.exp);
} else {
throw new Error(INVALID_ACCESS_TOKEN);
}
} else {
sessionStorage.removeItem(JWT_STORAGE_KEY);
delete axios.defaults.headers.common.Authorization;
}
} catch (error) {
console.error('Error during set session:', error);
throw error;
}
}